# Using the token-based authentication scheme

Use this approach to authenticate your identity and obtain a token that you can then use to call the Booking.com
Connectivity APIs.

When using this method you must first generate an access token and then call the Booking.com Connectivity APIs.

![Steps to follow when using OAuth2.0 tokens](/assets/steps-using-oauth-token.d2948bcf6457c47c48db9aef78f415da324bc48ac74c9a048a2852270292b9e3.b138ab4a.png)

## Step 1: Create a machine account

If you do not yet have a machine account using the `API token` authentication type, you can create one using the [Connectivity Portal.](https://connect.booking.com/machine-account)
Make sure to copy and store the `Client ID` and `Client Secret` for later use.

## Step 2: Generate an access token

Call the `token-based-authentication/exchange` endpoint by providing the `Client ID` and
`Client Secret` for your machine account.


```http
POST
https://connectivity-authentication.booking.com/token-based-authentication/exchange
```

The endpoint returns an access token that you can then use to call the Booking.com Connectivity APIs.

The token expires after one hour.
You can create up to 30 tokens per hour.

The encoded payload contains the following claims:

#### Standard claims

- sub: Specifies the subject identifier. For example, `sub: connectivity-auth-proxy`
- aud: Specifies the intended audience.
- iss: Specifies the issuer who created and signed the token. For example, `iss: urn://connectivity-modern-auth/v1`.
- exp: Specifies the expiration  time (Unix timestamp). For example,`exp: 1743761546`.
- iat: Specifies the issued at time (Unix timestamp). For example, `iat: 1743757946`
- jti: Specifies the JWT ID (unique identifier for this token). For example, `jti: b9cccca6-14ef-411e-90b7-5c2e0b74b738`


#### Custom claims

- Test: Specifies the intended environment for the token. For example, `test: false`
- machine_account_id: Specifies the machine account ID. For example, `machine_account_id`: `10697`
- provider_id: Specifies the Provider ID. For example, `provider_id: 1507`
- client_id: Specifies the Client ID. For example, `client_id`: 5B5DCB72-7FD4-11EF-B811-E70DD31774E2`


The API supports both XML and JSON formats.

**A JSON request example:**


```http
POST 'https://connectivity-authentication.booking.com/token-based-authentication/exchange' \
--header 'Content-Type: application/json' \
--data-raw '{
 "client_id": "client_id",
 "client_secret": "client_secret"
}'
```

**An XML request example:**


```xml
curl --location 'https://connectivity-authentication.booking.com/token-based-authentication/exchange' \
--header 'Content-Type: application/xml' \
--data '<request>
    <client_id>client_id</client_id>
    <client_secret>client_secret</client_secret>
</request>'
```

A successful response returns an access token.

**A JSON response example:**


```JSON
{
    "jwt": "someJWTexampleaXZpdHktYXV0aC1wcm94eSIsImF1ZCI6IiIsInRlc3QiOiJ0cnVlIiwibWFjaGluZV9hY2NvdW50X2lkIjoiOTg1MiIsImlzcyI6InVybjovL2Nvbm5lY3Rpdml0eS1tb2Rlcm4tYXV0aC92MSIsInByb3ZpZGVyX2lkIjoiMTUwNyIsImV4cCI6MTcyNDI1MjMzOSwiaWF0IjoxNzI0MjQ4NzM5LCJjbGllbnRfaWQiOiI3NEM3OTQ5Ni01RkMwLTExRUYtQTg2MC02QjIxQTYxRDZEMDgiLCJqdGkiOiJkOWU3YzU5ZC1mMDVjLTRhOWYtOTM5My1jMTRiNDEyM2U3N2IifQ.r5IhMI-1sRn1SPE4Vf_Txhssl7FS99ZwvX_3fs4y9s10lavcJ8dVQSX93T_T8_R5_v0207JcvlDxiI0VBujD98xG6x6XTkShJTmqyuhOQ6uV2CGwlbRfLSBD3-hIxqWQs-d0BIC9lJxKJui3v6raeq2BGjcC9gmHuYKE5lgM4HlYm682WyaOAaMNAmaTq2EkTH-OfwPzeDq4hu63h4v9UXaIw7IwwbA3WDYyEl3xFfpQBRa__Pyxrrpos9VTku2g7h0IKafBOCUaftzOHUDNXCHgdqqdCkwVk0QMxbzZuUu_WXEcgGoQ3XlZFThyD2xJKoqt0PX7jFvF2oLfp96jaQ",
    "ruid": "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
```

**An XML response example:**


```xml
<response>
    <jwt>"someJWTexampleaXZpdHktYXV0aC1wcm94eSIsImF1ZCI6IiIsInRlc3QiOiJ0cnVlIiwibWFjaGluZV9hY2NvdW50X2lkIjoiOTg1MiIsImlzcyI6InVybjovL2Nvbm5lY3Rpdml0eS1tb2Rlcm4tYXV0aC92MSIsInByb3ZpZGVyX2lkIjoiMTUwNyIsImV4cCI6MTcyNDI1MjMzOSwiaWF0IjoxNzI0MjQ4NzM5LCJjbGllbnRfaWQiOiI3NEM3OTQ5Ni01RkMwLTExRUYtQTg2MC02QjIxQTYxRDZEMDgiLCJqdGkiOiJkOWU3YzU5ZC1mMDVjLTRhOWYtOTM5My1jMTRiNDEyM2U3N2IifQ.r5IhMI-1sRn1SPE4Vf_Txhssl7FS99ZwvX_3fs4y9s10lavcJ8dVQSX93T_T8_R5_v0207JcvlDxiI0VBujD98xG6x6XTkShJTmqyuhOQ6uV2CGwlbRfLSBD3-hIxqWQs-d0BIC9lJxKJui3v6raeq2BGjcC9gmHuYKE5lgM4HlYm682WyaOAaMNAmaTq2EkTH-OfwPzeDq4hu63h4v9UXaIw7IwwbA3WDYyEl3xFfpQBRa__Pyxrrpos9VTku2g7h0IKafBOCUaftzOHUDNXCHgdqqdCkwVk0QMxbzZuUu_WXEcgGoQ3XlZFThyD2xJKoqt0PX7jFvF2oLfp96jaQ"</jwt>
    <ruid>XXXXXXXXXXXXXXXXXXXXXXXXXXX</ruid>
</response>
```

## Step 3: Call the Booking.com Connectivity APIs

Once you have a verified access token, you can use it to call the Booking.com Connectivity APIs.

A header example:


```http
Authorization: Bearer {JWT}
```

A request example:


```http
curl --location --request POST 'https://supply-xml.booking.com/hotels/xml/rooms' \
--header 'Authorization: Bearer uhTraWQiOiIxIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJjb25uZWN0aXZpdHktYXV0aC1wcm94eSIsImF1ZCI6IiIsInRlc3QiOiJmYWxzZSIsIm1hY2hpbmVfYWNjb3VudF9pZCI6IjEwNjY1IiwiaXNzIjoidXJuOi8vY29ubmVjdGl2aXR5LW1vZGVybi1hdXRoL3YxIiwicHJvdmlkZXJfaWQiOiIxNTA3IiwiZXhwIjoxNzI3NjkzMTI1LCJpYXQiOjE3Mjc2ODk1MjUsImNsaWVudF9pZCI6IjgxMThFQjRBLTdGMTAtMTFFRi1BQjNDLTY2OTQ2Q0NBMzQ1OCIsImp0aSI6ImY2ZTYwNWM5LWYwZTQtNGQxNy1iYmFiLWUzYmQxODMwOGQ4NyJ9.gnCS-MwgOa..Xx6meTcWkpXzstbV228ji_1KRM5K4wp8pm63hqKZngbgIBw4DVlhf5swct_eja86wDDiXd8LXjM3s-jBwsYGoOtUMa0IPk0gw-bPSrU7rgLl3GaUKirf43g5gqV4WlfwEYBsa_pkRYgveaKMXEEpaar1H0rBYXD9jBgrkOyL8Lf8FBGgKi_JvDolg0RxVxUNQiIuW7RDn5xHxdduwmdOEDHv6LQkcclSn4xyoElAXcOjuh0qS20wTf0Zabb2J3L2h2BuL0gKSdwrFlPLWBQYBXKUSK1fjYKarttqTbDDBK2nXgg26cImHByrkfnMm454BzQMRUTEN-g"' \
--header 'Content-Type: application/xml' \
--data-raw '<request>
  <hotel_id>8135188</hotel_id>
</request>'
```

## [Optional step] Get public key to verify token's signature

Get the public key using the JWKS (JSON Web Key Set) endpoint to verify the authenticity of the received token.


```http
GET
https://connectivity-authentication.booking.com/token-based-authentication/.well-known/jwks.json
```

Using the public key received from this endpoint, you can verify whether:

- The token was issued by a trusted source. For example, it was signed with the correct private key.
- The token has not been tampered with. For example, any modification would break the signature.


You can then trust the claims inside the token such as token creation time.

**A request example:**


```http
curl --location 'https://connectivity-authentication.booking.com/token-based-authentication/.well-known/jwks.json' \
--header 'Content-Type: application/json' \
```

**A JSON response example:**


```json
{
    "keys": [
        {
            "kty": "RSA",
            "kid": "1",
            "use": "sig",
            "alg": "RS256",
            "n": "zkzkaPpGKDu2dZxi1dN70xbfeBSg97nenjgrf9Tw0ai-x1ZYk_V6t6c74tqpNeJViNUhyCOYxOC3_LeOMXOah1FhXTJcCfCsr0zO1oHL1n_ytt8K6ANLC2FMc7V-WlIDo836QUFfJOP35fWvBorTVpPEwbqZuKDP-h8vGxAWYjyaAzcbEwuPsXMEa6nEGcDJLExq4n1jYtrsNLqDD_EEQDtZojvOTcSuR4XN_rHOJlLXeR3MuP4HDTk4uR1KPa2VXJ-xugnjOmpkVOP1gsYwDnmyq5b304Vf7a3HJUdClVQ5VtN2XRQfUbGNYsyrb7Ljn-SyfVKJ2JXMJChVCsnNSw",
            "e": "AQAB"
        }
    ]
}
```

### Exceeding token verification limit

The `https://connectivity-authentication.booking.com/token-based-authentication/.well-known/jwks.json` endpoint has a rate limiting of maximum 300 requests per hour. Once this threshold is breached, the endpoint returns the rate limit error as a response.

### Verify the token's signature

The JWT issued in step 2 has the following three parts:

- HEADER
- PAYLOAD
- SIGNATURE


Every decoded JWT header contains a field called `kid` (key ID). This value tells us the key that was used to sign the token.

Using the response from the JWKS endpoint, you can look for the key that has the same kid (kid: 1). Once you find the key, you can use a common JWT library to reconstruct the RSA public key by using other fields in the response (For example, `n` and `e`).

Using this public key, the library verifies the token’s signature to ensure that it was indeed signed by the trusted issuer and that the contents of the token have not been modified.

If the verification is successful, you can safely trust the token and use its claims. For example, you can check whether the token has expired. For token expiration, we recommend to use JWT’s claim `exp` field.

## Authentication failure

The token expires every one hour.
The API returns `HTTP 401` for a failed authentication attempt when the token expires.
Make sure to refresh the token before it expires by calling the `token-based-authentication/exchange` endpoint.

A response example when using an expired token:


```JSON
{
    "code": "401",
    "message": "JWT is wrong or expired, please refresh your JWT."
}
```

## Common errors

This section lists common errors while using the `token-based-authentication/exchange` endpoint and how to resolve them.

### Missing required parameters

Failure to provide a `client_id` or `client_secret` parameter in the request body, returns an `HTTP 400` response:


```JSON
{
    "ruid": "XXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "status": "400",
    "error": "Bad Request",
    "message": "client_id and client_secret parameters should exist."
}
```

### Using incorrect Content-Type header

Providing a mismatching `Content-Type` header can also return an `HTTP 400` response.

The following table lists the supported `Content-Type` header values:

| Request body type | Content-Type header |
|  --- | --- |
| JSON | `application/json` |
| XML | `application/xml` |



```JSON
{
    "ruid": "XXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "status": "400",
    "error": "Bad Request",
    "message": "client_id and client_secret parameters should exist."
}
```

If the `Content-Type` header does not exist, or if it is not one of the above-mentioned values, then the API returns an `HTTP 415` error.

### Using invalid API credentials

Providing an invalid or revoked/disabled `client_id`/`client_secret` parameter in the request body, returns an `HTTP 401` response:


```JSON
{
    "ruid": "XXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "status": "401",
    "error": "Unauthorized",
    "message": "Invalid or revoked client_id/client_secret."
}
```

### Using incorrect HTTP method

Calling the `token-based-authentication/exchange` endpoint with a `GET` or `PUT` method, returns an `HTTP 405` response.
Make sure to use the `POST` method


```JSON
{
    "ruid": "XXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "status": "405",
    "error": "Method Not Allowed",
    "message": "This endpoint only supports POST requests."
}
```

## Exceeding token generation limit

If you request for more than 30 tokens within an hour, you breach the rate limit and the API returns an `HTTP 429` error.
Successive `HTTP 429` errors can trigger latency.


```JSON
{
    "ruid": "XXXXXXXXXXXXXXXXXXXXXXXXXXX",
    "status": "429",
    "error": "Too Many Requests",
    "message": "The rate limit was exceeded for the client_id."
}
```

## FAQs

**1. Will migrating machine accounts delete or disable existing or old ones?**
No.

**2. Is IP **allowlisting** mandatory?**
No, if no IP address is specified, then we won’t filter requests by IP. If one or more IPs are specified instead, the filter will be active and only requests from the listed IPs will be accepted.

**3. Is it possible to delete machine accounts?**
Only Token based machine accounts can be deleted. A machine account needs to be disabled first before it can be deleted.

**4. Can both credential-based authentication and token-based machine accounts be used at the same time?**
Yes, you can use both machine accounts until December 31, 2025. On this date, all machine accounts with credential-based authentication will be sunset and will no longer work. Make sure to use the new accounts with the Token-based Authentication method.

**5. How can I open the .zip file?**
The file cannot be unzipped with the default MacOS app. You can unzip it using Terminal or specialised apps such as The Unarchiver. Windows’ default app can manage the file correctly.

**6. What is the rate limit of the endpoint to get tokens?**
The rate limit on the exchange end point is 30 per hour. In other words, you can have up to 30 tokens at any point in time. Each token expires 1 hour after the generation.

**7. Is the rate limited by IP or machine account?**
The exchange API rate limit is limited by machine account.

## Related links

-> [Authentication best practices](/connectivity/docs/authentication-best-practices)