API Reference
The Subcent REST API gives you programmatic access to vaults, agents, payments, policies, escrows, merchants, and webhooks. All endpoints are JSON-based and require Bearer token authentication.
Base URL#
https://api.subcent.io/v1
For testnet:
https://testnet-api.subcent.io/v1
Authentication#
Every request must include an Authorization header with a valid API key:
Authorization: Bearer <token>
There are three token types:
| Prefix | Scope | Use Case |
|---|---|---|
| sc_live_ | Full account access (mainnet) | Server-side integrations |
| sc_test_ | Full account access (testnet) | Development and testing |
| sc_agent_ | Single vault, payment-only | Issued to AI agents |
Request Format#
All request bodies must be JSON with the Content-Type: application/json header. String amounts are in decimal USDC (e.g., "25.00").
Response Format#
Successful responses return JSON with a 2xx status code. The shape varies by endpoint and is documented on each endpoint page.
Error Response Format#
All errors return a consistent JSON structure:
{
"error": "error_code_string",
"message": "Human-readable description of what went wrong"
}
Error Codes#
The following error codes may be returned by any endpoint:
| Error Code | HTTP Status | Description |
|---|---|---|
| vault_not_found | 404 | The specified vault does not exist |
| vault_frozen | 403 | The vault is frozen and cannot process transactions |
| insufficient_balance | 400 | The vault does not have enough USDC to cover the payment |
| agent_not_authorized | 403 | The agent is not authorized for this vault |
| agent_revoked | 403 | The agent's access has been revoked |
| policy_violation | 400 | The payment request violates the active spending policy |
| policy_not_found | 404 | No policy found for the specified ID or agent |
| merchant_not_found | 404 | The specified merchant does not exist |
| merchant_suspended | 403 | The merchant account is suspended |
| approval_timeout | 408 | The approval request timed out without a decision |
| escrow_expired | 400 | The escrow has passed its expiration time |
| escrow_already_released | 400 | The escrow funds have already been released |
| escrow_not_found | 404 | The specified escrow does not exist |
| payment_not_found | 404 | The specified payment does not exist |
| webhook_not_found | 404 | The specified webhook does not exist |
| invalid_state | 400 | The resource is in a state that does not allow this operation |
| invalid_policy_proof | 400 | The on-chain policy proof is invalid or tampered |
| rate_limit_exceeded | 429 | Too many requests -- slow down |
| chain_error | 502 | An error occurred communicating with the blockchain |
| internal_error | 500 | An unexpected internal server error |
Rate Limiting#
The API enforces a rate limit of 100 requests per minute per API key. When exceeded, the API returns a 429 status with the rate_limit_exceeded error code.
Rate limit headers are included on every response:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests per window (100) |
| X-RateLimit-Remaining | Requests remaining in current window |
| X-RateLimit-Reset | Unix timestamp when the window resets |
Pagination#
List endpoints use cursor-based pagination. The maximum page size is 200 items.
Query Parameters#
| Parameter | Type | Default | Description |
|---|---|---|---|
| limit | integer | 50 | Number of items to return (max 200) |
| cursor | string | -- | Cursor from a previous response to fetch the next page |
Response Shape#
{
"payments": [...],
"has_more": true
}
When has_more is true, take the last item's ID and pass it as the cursor parameter to retrieve the next page.
Idempotency#
For POST endpoints that create resources, you can pass an Idempotency-Key header to safely retry requests without creating duplicates:
Idempotency-Key: your-unique-key-here
Keys expire after 24 hours.
API Endpoints#
Vaults#
| Method | Path | Description | |---|---|---| | POST | /v1/vaults | Create a new vault | | GET | /v1/vaults/:id | Get vault details | | POST | /v1/vaults/:id/freeze | Freeze a vault | | POST | /v1/vaults/:id/unfreeze | Unfreeze a vault |
Payments#
| Method | Path | Description | |---|---|---| | POST | /v1/payments/request | Request a payment | | GET | /v1/payments/:id | Get payment details | | GET | /v1/payments | List payments | | POST | /v1/payments/:id/approve | Approve a pending payment | | POST | /v1/payments/:id/reject | Reject a pending payment |
Agents#
| Method | Path | Description | |---|---|---| | POST | /v1/agents | Register a new agent | | DELETE | /v1/agents/:id | Revoke an agent |
Policies#
| Method | Path | Description | |---|---|---| | POST | /v1/policies | Create a policy | | GET | /v1/policies/:id | Get a policy | | PUT | /v1/policies/:id | Update a policy |
Escrows#
| Method | Path | Description | |---|---|---| | POST | /v1/escrows | Create an escrow | | GET | /v1/escrows/:id | Get escrow details | | GET | /v1/vaults/:id/escrows | List escrows for a vault | | POST | /v1/escrows/:id/release | Release escrow funds | | POST | /v1/escrows/:id/refund | Refund escrow funds | | POST | /v1/escrows/:id/dispute | Dispute an escrow |
Merchants#
| Method | Path | Description | |---|---|---| | POST | /v1/merchants/register | Register a merchant | | GET | /v1/merchants/:id | Get merchant details |
Webhooks#
| Method | Path | Description | |---|---|---| | POST | /v1/webhooks | Create a webhook | | GET | /v1/webhooks | List webhooks | | DELETE | /v1/webhooks/:id | Delete a webhook |