Authentication
To work with coupons and the balance, the partner must obtain a client JWT. The token is issued after the username and password are verified and determines which client’s data can be accessed.
Login credentials
The manager provides the username and password. Store them on the server side and never expose them to a browser, mobile application, or third-party service.
The examples use this placeholder address:
BASE_URL="https://coupon-api.example.com"
Replace it with the base URL provided by your manager.
Obtaining a JWT
Use:
POST /api/partner/login
The login request itself does not require authentication.
The old API used
POST /api/v2/loginfor authentication. This endpoint remains supported, but new integrations should usePOST /api/partner/login. All differences are described in Migrating from the old API.
Example:
curl --request POST \
--url "$BASE_URL/api/partner/login" \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '{
"username": "partner-demo",
"password": "strong-password"
}'
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
username | string | Yes, if login is not provided | Primary field for the partner username. |
login | string | Yes, if username is not provided | Compatibility alias for username. New integrations should use username. |
password | string | Yes | Partner password. |
Provide only one username field: either username or login.
Successful response
{
"code": 1,
"body": {
"token": "eyJhbGciOiJIUzI1NiJ9...",
"username": "partner-demo"
},
"error_code": null,
"error_message": null,
"date": 1784970000000,
"time_ms": 35,
"path": "/api/partner/login"
}
body fields
| Field | Type | Description |
|---|---|---|
token | string | Signed client JWT. |
username | string | Authenticated client username. |
Using the token
Store body.token and include it in every protected request:
Authorization: Bearer <client_token>
Example:
curl --request GET \
--url "$BASE_URL/api/partner/coupons/active" \
--header "Accept: application/json" \
--header "Authorization: Bearer <client_token>"
Important:
- there must be exactly one space between
Bearerand the token; - use the JWT obtained through the client endpoint
/api/partner/login; - an administrator JWT cannot be used;
- the
X-Client-Idheader is not used and cannot switch access to another client.
Expiration and signing in again
Treat the JWT as an opaque access token. The client does not need to parse its contents or verify its signature independently.
Use the token for as long as the API accepts it. If a protected method returns HTTP 401, sign in again and retry the request with the new JWT.
The Client API does not provide a separate token refresh method.
Do not sign in again before every operation unless necessary. A JWT can be safely reused across requests until it expires or is revoked.
Login errors
If the credentials are not accepted, the API usually returns HTTP 200 with a business error:
{
"code": 0,
"body": null,
"error_code": 1003,
"error_message": "Wrong login or password",
"date": 1784970000000,
"time_ms": 5,
"path": "/api/partner/login"
}
Possible responses:
| Result | error_message | Meaning |
|---|---|---|
code = 1 | — | Login succeeded; the JWT is available in body.token. |
error_code = 1002 | Not all params | The username or password was not provided. |
error_code = 1003 | Wrong login or password | The username is unknown or the password is incorrect. |
error_code = 1004 | Client account is disabled | The client account is disabled. |
error_code = 1006 | Client access has expired | The client access period has expired. |
error_code = 1007 | Insufficient balance | The client account balance is zero or negative. |
HTTP 400 | — | The JSON is malformed or a field contains an incompatible type. |
HTTP 500 | — | Internal service error. |
All listed error_code values are business errors: they are returned with HTTP 200 and code = 0.
An unknown username and an incorrect password are intentionally not distinguished and both return error 1003. Account states are reported separately: when 1004, 1006, or 1007 is returned, retrying the request with the same credentials will not help. Contact the manager to enable the account, extend access, or replenish the client balance.
Error 1007 is returned at login when the balance is zero or negative. If the balance is positive, login is allowed even when the amount is insufficient for a particular coupon placement request. In that case, POST /api/partner/coupons/place returns 507, Insufficient balance.
The compatible POST /api/v2/login endpoint retains the old behavior: every login failure is returned as error_code = 99 with Wrong login or password.
Always check both the HTTP status and the code field in the JSON response.
Errors from protected requests
After a successful login, two primary authorization responses are possible:
| HTTP status | Cause | What to do |
|---|---|---|
401 | The token is missing, malformed, expired, or no longer valid. | Sign in again and send the request with the new JWT. |
403 | The token does not have the client role, or access is forbidden. | Verify that a client JWT is being used. Contact the manager if the problem persists. |
Do not start an infinite reauthentication loop. If a newly issued JWT immediately receives 401 or 403, stop retrying and check the credentials and account state.
Secure storage
- Use HTTPS.
- Store the username, password, and JWT only on the server side.
- Do not write the password or full token to logs.
- Do not include the JWT in a URL or query parameters.
- Do not provide one partner’s client token to another partner.
- Restrict credential access to components that require the Client API.
Next step: review the common request and response conventions.