API reference

The full machine-readable spec lives at /api/v1/openapi.json — drop it into any OpenAPI viewer (Swagger UI, Stoplight, Postman, Insomnia, etc.) for an interactive explorer.

Conventions

  • Base URL in production: https://api.sorenpay.com
  • All authenticated requests carry Authorization: Bearer apk_…
  • All POSTs and PATCHs accept Idempotency-Key (UUIDv4, 24h cache)
  • Live mode money-movement routes require workspace.kyb_status === 'approved'
  • All inbound webhooks verify HMAC-SHA256 over raw body with ±5min replay window

Resources

| Resource | Routes | |---|---| | Workspaces | POST /api/workspaces, GET /api/workspaces | | API keys | POST/GET/DELETE /api/auth/keys | | Cards | POST/GET /api/cards, GET/PATCH /api/cards/[id] | | Cardholders | POST/GET /api/cardholders | | Physical cards | POST /api/physical-cards | | Treasury | GET /api/treasury, POST /api/treasury/deposits | | Ramp | onramp/offramp sessions + quotes | | Intl payments | quote + originate + lookup | | Agents | register + submit intent + audit log | | MCP | JSON-RPC 2.0 endpoint | | Checkout | merchant sessions + customer flow | | Webhooks | inbound + outbound event spec |

Errors

All errors return JSON shaped:

{
"error": "<short_machine_code>",
"detail": "Optional human-readable message"
}

| Status | When | |---|---| | 400 | Bad request body (Zod parse failure) | | 401 | Missing or invalid apk_ token | | 403 | Missing required scope | | 404 | Resource not found (or not in your workspace) | | 409 | State conflict (e.g., kyb_required, cardholder_required) | | 422 | Idempotency-key mismatch (different body, same key) | | 429 | Rate limit hit; see x-ratelimit-reset-ms | | 500 | Server error — Sentry will catch it; please retry |

Versioning

We follow the OpenAPI spec at /api/v1/openapi.json for the v1 surface. Breaking changes will move to /api/v2/… without removing v1 for at least 12 months.