Documentation menu
Docs / Build
API conventions
Authentication, idempotency, errors, pagination, rate limits and versioning.
Authentication#
POST /oauth/token with grant_type=client_credentials, your client_id and client_secret (form encoded). Send the token as Authorization: Bearer <access_token> on every other request. Tokens last 900 seconds. An expired or invalid token returns authentication_required (401); get a new token and retry.
Idempotency#
Every request that creates or changes a record requires an Idempotency-Key header: a unique value such as a UUID, up to 255 characters.
| Situation | Result |
|---|---|
| Same key and same request within 24 hours | The original response, without doing anything twice |
| Same key, different request | idempotency_key_reused (409) |
| Same key while the first request is still running | idempotency_key_in_use (409); retry after a short wait |
| The first request failed with an error | Nothing is stored; fix the cause and retry with the same key |
Always retry a request that timed out or returned 500 or 503 with the same key.
Errors#
{ "error": { "code": "limit_exceeded", "message": "The amount exceeds the daily amount limit.", "param": "amount", "request_id": "req_8Hw2Kd9Lq4Zx7c", "details": { "limit": "daily_amount" } } }Build your logic on code, which is stable. message is for people and can change. param names the field at fault and details adds context. Every code is listed in the API reference.
| Status | Meaning |
|---|---|
| 400 | The request is malformed or a field is missing or invalid |
| 401 | Missing, invalid or expired credentials |
| 403 | Not allowed, for example a flow not enabled for your program |
| 404 | The record does not exist, or belongs to another Tenant |
| 409 | A conflict with the record's status, or an idempotency conflict |
| 422 | Valid request that business rules refuse, for example insufficient_funds |
| 429 | Rate limited; see Retry-After |
| 500, 503 | Retry with the same Idempotency-Key |
Request IDs#
Every response has an A2A-Request-Id header, also in error bodies as request_id. Log it, and quote it when you contact support. The portal's Request logs show the full request and response for each ID.
Pagination#
List endpoints return data, has_more and next_cursor. Pass cursor=<next_cursor> for the next page and limit (1 to 100, default 25) for the page size. Lists are newest first.
Rate limits#
Each response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. Above the limit, the API returns 429 with Retry-After in seconds. Production limits are agreed for your program; the sandbox limit is set in the portal settings.
Versioning#
The API version is in the path (/v1). Within a version, changes are additive only: new endpoints, new optional fields, new event types and new enum values. Write your code to ignore fields and events it does not know. Breaking changes come in a new version, announced in the changelog in advance.
Formats#
- JSON in UTF-8 over HTTPS with TLS 1.2 or later.
- Amounts in integer cents, in USD.
- Times in ISO 8601, UTC. Business dates in US Eastern Time.
Questions about this page? Contact developer support.