API Overview
Phoenix Pay REST API conventions, authentication, error handling, and pagination.
API Overview
The Phoenix Pay API is a JSON REST API. All endpoints return JSON responses and require a valid Zitadel bearer token for authentication (except the public signing key endpoint).
Base URL
https://pay.phoenixverse.io/apiAll endpoint paths in this documentation are relative to this base URL.
Authentication
Every API request (except /api/.well-known/signing-key) must include a valid JWT access token in the Authorization header.
curl https://pay.phoenixverse.io/api/deposits \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json"See the Authentication guide for details on obtaining and managing tokens.
Request Format
- Content-Type:
application/jsonfor all POST/PUT requests - Character encoding: UTF-8
- Amounts: Passed as decimal strings (e.g.,
"50.00","0.001") to avoid floating-point precision issues
{
"reference_id": "order-12345",
"amount": "50.00",
"currency": "USDT"
}Always send amounts as strings, not numbers. "50.00" is correct; 50.00 may lose precision during JSON parsing.
Response Format
All successful responses return JSON. Single-resource endpoints return the resource directly. List endpoints return a data array with a meta pagination object.
{
"id": "01912e4a-7b3c-7def-8a90-1234567890ab",
"reference_id": "order-12345",
"type": "deposit",
"status": "awaiting_payment",
"psp": "nowpayments",
"requested_amount": "50.00",
"received_amount": null,
"currency": "USDT",
"pay_currency": "usdttrc20",
"pay_amount": "50.00",
"checkout_url": null,
"pay_address": "TXrk4d5x7Bj3e6g7Y8Zw...",
"expires_at": "2026-03-11T14:30:00Z",
"inserted_at": "2026-03-11T12:30:00Z",
"updated_at": "2026-03-11T12:30:00Z"
}{
"data": [
{
"id": "01912e4a-7b3c-7def-8a90-1234567890ab",
"reference_id": "order-12345",
"type": "deposit",
"status": "settled",
"..."
},
{
"id": "01912e4b-8c4d-7def-9b01-2345678901bc",
"reference_id": "order-12346",
"type": "deposit",
"status": "awaiting_payment",
"..."
}
],
"meta": {
"page": 1,
"limit": 25,
"total": 142,
"total_pages": 6,
"has_next": true,
"has_prev": false
}
}Pagination
List endpoints use offset-based pagination with the following query parameters:
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page | integer | 1 | - | Page number (1-indexed) |
limit | integer | 25 | 100 | Number of results per page |
The response meta object contains:
| Field | Type | Description |
|---|---|---|
page | integer | Current page number |
limit | integer | Results per page |
total | integer | Total number of matching records |
total_pages | integer | Total number of pages |
has_next | boolean | Whether there is a next page |
has_prev | boolean | Whether there is a previous page |
curl "https://pay.phoenixverse.io/api/deposits?page=2&limit=10" \
-H "Authorization: Bearer <token>"Error Format
Error responses include an error field with a human-readable message.
{
"error": "missing required parameter: reference_id"
}For validation errors (400) and processing errors (422), the error field describes what went wrong. For server errors (500), a generic "internal_error" message is returned.
Common HTTP Status Codes
| Status | Meaning |
|---|---|
200 OK | Request succeeded |
201 Created | Resource created successfully (deposits, payouts) |
400 Bad Request | Missing or invalid request parameters |
401 Unauthorized | Missing or invalid authentication token |
403 Forbidden | Authenticated but insufficient permissions |
404 Not Found | Resource does not exist or belongs to a different tenant |
422 Unprocessable Entity | Request was well-formed but could not be processed (e.g., no PSP configured for the requested currency) |
500 Internal Server Error | Unexpected server error |
See the Status Codes page for a complete reference.
Rate Limiting
Phoenix Pay applies rate limiting to protect against abuse. Current limits:
| Endpoint Type | Limit |
|---|---|
Create endpoints (POST) | 100 requests/minute per tenant |
Read endpoints (GET) | 300 requests/minute per tenant |
| Webhook endpoints | Unlimited (PSP-initiated) |
When rate limited, the API returns a 429 Too Many Requests response with a Retry-After header indicating when to retry.
Rate limits are applied per tenant (organization), not per token. Multiple service accounts under the same organization share the same rate limit.