Getting started
Authentication
OAuth 2.0 client credentials: mint a token once a day, send it as a bearer on every call.
OAuth 2.0 client credentials, the same grant Guesty’s Open API uses, so an integration written against one needs a different token URL and nothing else.
The flow
- Create credentials. Settings › Integrations issues a client ID and a client secret. The secret is shown once; only its hash is stored.
- Exchange them for a token. POST the form to
/oauth2/token. The answer is a bearer token that lasts 24 hours. - Send the bearer.
Authorization: Bearer <token>on every call. Cache the token and re-use it until a 401 tells you it expired; then mint another.
The token endpoint
Send the form as application/x-www-form-urlencoded. HTTP Basic with client_id:client_secret is accepted too, and so is a JSON body with the same three
fields. The full contract is on the reference page.
Request
curl -X POST "https://go.quarters.live/api/v1/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=qc_YOUR_CLIENT_ID" \
-d "client_secret=qs_YOUR_CLIENT_SECRET"Response · 200
{
"token_type": "Bearer",
"access_token": "qat_…",
"expires_in": 86400
}The token endpoint fails in RFC 6749’s own shape, error plus error_description, because that is what an OAuth client library reads. Every other
endpoint fails as described under Errors.
| Status | error | When |
|---|---|---|
| 400 | invalid_request | client_id or client_secret missing, or a body that is neither form-encoded nor JSON. |
| 400 | unsupported_grant_type | Anything but grant_type=client_credentials. |
| 401 | invalid_client | Unknown client id, wrong secret, or credentials that were revoked. |
Caching and expiry
A token is good for 24 hours from the moment it is issued, and expires_in says so in seconds.
Keep one per credential set in your own process or cache and re-use it for every call; minting a token
per request is a wasted round trip and a wasted row.
The simplest correct strategy: hold the token with the time you got it, mint a new one when it is
older than 23 hours, and also whenever a call answers 401 unauthorized, which covers
a clock that drifted and a credential that was revoked.
Revocation
Revoking a credential set under Settings › Integrations invalidates every token issued from it at once; the next call answers 401. Credential sets are independent: a second set for a second system gets its own tokens, and revoking one leaves the other working. Create one set per integration so a leak costs one rotation, not all of them.
Server to server only
There are no CORS headers on purpose. Credentials and tokens belong on your server, never in a browser; a booking page calls your backend, and your backend calls Quarters.