API reference
Introduction
REST over HTTPS. JSON request and response bodies. Bearer authentication. Prefixed ids. Cursor pagination. Idempotent creates.
Base URLs#
| Environment | Base URL | Key prefix | Chain |
|---|---|---|---|
| Production | https://api.payday.sh | payday_live_ | Monad, 143 |
| Sandbox | https://api.sandbox.payday.sh | payday_test_ | Monad testnet, 10143 |
All routes are under /v1. OpenAPI 3.1: /openapi.json on each origin; rendered at /docs.
Authentication#
Authorization: Bearer payday_live_…
Content-Type: application/json- Merchant routes accept an API key or a dashboard session token in the same header. Full account authority; not scoped.
- One active key per account. Issuance replaces it.
- Rotation: previous key valid 24 hours. Revocation: immediate, including the grace key.
- Key management (
/v1/account/api-key) accepts sessions only. A key is refused with401 identity_unauthorized. - Keys are returned once and stored as SHA-256.
- Payer routes take no credential.
Ids#
UUIDs behind a resource prefix. Only the canonical form is accepted: a bare UUID or wrong prefix in a path is 404; in a body or query, 400 invalid_request.
| Prefix | Resource |
|---|---|
| dr_ | deposit request |
| cus_ | customer |
| iss_ | issuer identity |
| pa_ | payout address |
| att_ | attachment |
| wh_ | webhook endpoint |
| whd_ | webhook delivery |
| evt_ | webhook event |
| va_ | verification attempt |
| rec_ | recovery ledger entry |
| acct_ | account |
Errors#
HTTP/1.1 400 Bad Request
X-Request-Id: 0198f80c-5555-7dc1-a369-90556a64f700
{
"error": { "code": "invalid_request", "message": "missing field `amount`" },
"request_id": "0198f80c-5555-7dc1-a369-90556a64f700"
}X-Request-Idon every response. A caller-supplied value (≤128 printable bytes) is echoed; otherwise a UUIDv7 is generated. JSON errors repeat it asrequest_id.400 invalid_request: malformed JSON, missing or unknown field, wrong type, missing JSON content type, control character. The message names the field. Unknown fields are rejected on every body.404 <resource>_not_found: missing, malformed, or another account's id.- Full code table: Errors.
Conventions#
- Creates:
201with the resource. Deletes and disables:204. PATCHis partial. Omitted fields are unchanged; explicitnullclears. The merged record is validated whole.- Lists are enveloped under the plural (
deposit_requests,customers,issuers,payout_addresses,webhooks,deliveries,transfers). - Clients must tolerate unknown fields and branch only on documented values.
Pagination#
limit 1–100, default 20. next_cursor is the last item's id or null; pass it as starting_after. Newest first.
GET /v1/deposit-requests?status=partially_deposited&limit=50
GET /v1/deposit-requests?limit=50&starting_after=dr_0198f80c-…Idempotency#
POST /v1/deposit-requests requires Idempotency-Key (1–255 bytes). Same key, same document: 200 with the original and Idempotency-Replayed: true. Same key, different immutable field: 409 idempotency_conflict.
Formats#
| Kind | Format |
|---|---|
| USDC amounts | Decimal string, six fractional digits ("25.000000"), with an integer *_base_units counterpart ("25000000"). |
| Timestamps | RFC 3339, UTC, second precision, Z suffix. Unix seconds only where stated. |
| Addresses | EIP-55 on output. Any case on input. |
| Block numbers, log indexes | Decimal strings. |
| Hashes, signatures | 0x-prefixed lowercase hex. |
| Text | UTF-8. No C0 control characters. Line breaks and tabs preserved. |
Rate limits#
Per account, API-key traffic: token bucket of 60, refill 1/s. Rejection: 429 rate_limited, Retry-After: 1.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1756728061Body limits#
| Routes | Limit |
|---|---|
| Deposit requests, customers, issuers, attachments, webhooks | 64 KiB |
| Account key | 16 KiB |
| Payer verification writes | 8 KiB |
Exceeded: 413 payload_too_large. PDF bytes go to the presigned upload URL, never to the API.
CORS#
- Merchant routes: the dashboard origin only.
- Payer reads:
Access-Control-Allow-Origin: *. - Payer writes: the hosted checkout origin only.