# Obtain access token Building with an AI agent? Start at https://docs.payme.io/agents.md - Sandbox: your partner domain on the Keep sandbox: `POST https://.keep.co.il/oauth2/token` - Production: your partner domain: `POST https://.keep.co.il/oauth2/token` ## Credentials - Request body field `client_secret` (required): Your client secret - Request body field `refresh_token` (optional): Required when `grant_type` is `refresh_token`. A refresh token works once: the response carries a new one, and the old access token stops working. Use this endpoint to obtain an access token using Client Credentials or to refresh an existing token. ## Parameters This endpoint takes no path, query or header parameters. ## Request body Content type: `application/x-www-form-urlencoded` | Field | Type | Required | Description | | --- | --- | --- | --- | | `grant_type` | string | yes | The grant type Allowed values: `client_credentials`, `refresh_token`. | | `scope` | string | no | Space-separated scopes. Send `partner-api` with `grant_type=client_credentials`. The field is optional in the request, but a token issued without a scope is refused with `403` by every Keep endpoint. With `grant_type=refresh_token` it is not needed: the new token keeps the scopes of the original one. | | `client_id` | string | yes | Your client ID | | `client_secret` | string | yes | Your client secret | | `refresh_token` | string | no | Required when `grant_type` is `refresh_token`. A refresh token works once: the response carries a new one, and the old access token stops working. | ### Request example ```json { "grant_type": "client_credentials", "scope": "partner-api", "client_id": "your-client-id", "client_secret": "your-client-secret" } ``` ## Code samples ### curl ```bash curl -X POST 'https://.keep.co.il/oauth2/token' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'scope=partner-api' \ --data-urlencode 'client_id=your-client-id' \ --data-urlencode 'client_secret=your-client-secret' ``` ### Node.js ```javascript const response = await fetch("https://.keep.co.il/oauth2/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: new URLSearchParams({ "grant_type": "client_credentials", "scope": "partner-api", "client_id": "your-client-id", "client_secret": "your-client-secret" }), }); console.log(await response.text()); ``` ### Python ```python import requests response = requests.post( "https://.keep.co.il/oauth2/token", data={ "grant_type": "client_credentials", "scope": "partner-api", "client_id": "your-client-id", "client_secret": "your-client-secret", }, ) print(response.text) ``` ### PHP ```php .keep.co.il/oauth2/token'); curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/x-www-form-urlencoded', ], CURLOPT_POSTFIELDS => http_build_query([ 'grant_type' => 'client_credentials', 'scope' => 'partner-api', 'client_id' => 'your-client-id', 'client_secret' => 'your-client-secret', ]), ]); $response = curl_exec($ch); curl_close($ch); echo $response; ``` ## Responses ### 200 — Successful authentication (success) | Field | Type | Description | | --- | --- | --- | | `token_type` | string | | | `access_token` | string | JWT access token | | `refresh_token` | string | Refresh token | | `expires_in` | integer | Access token lifetime in seconds | | `refresh_expires_in` | integer | Refresh token lifetime in seconds | | `scope` | string | Granted scopes | ### 400 — Invalid request. `error` is `invalid_request`, for an unknown refresh token. (error) | Field | Type | Description | | --- | --- | --- | | `error` | string | | | `error_description` | string | | ### 401 — Unauthorized. When `client_id` or `client_secret` is missing, the body is the plain text `Unauthorized`, not JSON. (error) | Field | Type | Description | | --- | --- | --- | | `error` | string | `unauthorized_client` (wrong client ID or secret) or `unauthorized_scope` (scope not granted to this client) | | `error_description` | string | |