Obtain access token
- Sandbox: your partner domain on the Keep sandbox:
POST https://<partner_domain>.keep.co.il/oauth2/token
- Production: your partner domain:
POST https://<partner_domain>.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
{
"grant_type": "client_credentials",
"scope": "partner-api",
"client_id": "your-client-id",
"client_secret": "your-client-secret"
}
Code samples
curl
curl -X POST 'https://<partner_domain>.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
const response = await fetch("https://<partner_domain>.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
import requests
response = requests.post(
"https://<partner_domain>.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
$ch = curl_init('https://<partner_domain>.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 |
|