# Partners API Building with an AI agent? Start at https://docs.payme.io/agents.md Overview of the Keep Partner API for integrators: authentication methods, the token lifecycle, best practices, and the error formats and rate limit partner endpoints return. PayMe Book-keeping Partner API for integrators. ## Overview > **Authentication Methods** > 1. Client Credentials - Server-to-server authentication > 2. Refresh Token - Token renewal ## Token Lifecycle > 1. Obtain tokens via Client Credentials > 2. Use access_token for API requests > 3. When access_token expires (check expires_in) > 4. Use refresh_token to obtain new access_token > 5. When refresh_token expires, re-authenticate ## Best Practices 1. **Store credentials securely** - Never expose `client_secret` in client-side code 2. **Use HTTPS** - All API requests must use HTTPS 3. **Implement token refresh** - Proactively refresh tokens before expiration 4. **Handle errors gracefully** - Implement retry logic with exponential backoff ## Errors and rate limits - Token endpoint errors return `error` and `error_description`. A wrong client ID or secret returns HTTP 401 `unauthorized_client`; a scope not granted to your client returns HTTP 401 `unauthorized_scope`; an unknown refresh token returns HTTP 400 `invalid_request`. - Guard and validation HTTP errors normally include `statusCode` and `message`, plus `correlationId` and `category`. Some legacy endpoints add `status`; unhandled errors can omit `message`. `message` is a list for validation errors. - A missing or expired access token returns HTTP 401. A token without the required scope returns HTTP 403. - `/api/public/sellers`, `/api/public/expenses` and `/api/public/plans` are rate limited per partner domain and return HTTP 429 when the limit is exceeded. The `429` body is plain text, not the JSON error shape; the `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` headers show the quota. - Every response carries an `X-Request-Id` header, and an `X-Correlation-Id` header beside it. Quote them when contacting support. If you send your own `X-Request-Id`, it is echoed back. - The document-failure webhook example uses `errorCode` `TAX_AUTHORITY_REJECTED` ("Document rejected by tax authority - invalid VAT number"). ## Endpoints - [Obtain access token](/keep/partners-api/gettoken): POST /oauth2/token - [Create seller](/keep/partners-api/createseller): POST /api/public/sellers/create - [Get seller](/keep/partners-api/getsellerbyid): GET /api/public/sellers/{sellerId} - [Get available plans](/keep/partners-api/getpartnerplans): GET /api/public/plans - [List expenses](/keep/partners-api/listpublicexpenses): GET /api/public/expenses - [Upload expense document](/keep/partners-api/uploadpublicexpense): POST /api/public/expenses - [Update expense](/keep/partners-api/updatepublicexpense): PATCH /api/public/expenses/{expenseId} - [Update seller](/keep/partners-api/updatesellerbyid): PUT /api/public/sellers/{sellerId}/update - [Set seller billing plan](/keep/partners-api/setsellerplan): POST /api/public/plans/activate - [List income documents](/keep/partners-api/listincomedocuments): GET /partner/api/documents/income - [Create manual income document](/keep/partners-api/createmanualincomedocument): POST /partner/api/documents/income/manual - [Get financial checkpoints](/keep/partners-api/getcheckpoints): GET /partner/api/statistic/checkpoints - [Get tax predictions](/keep/partners-api/gettaxpredictions): GET /partner/api/statistic/tax-predictions