Every Infra service follows the same conventions. Learn them once and they apply across Auth-Edge, Payments, Products, Subscriptions, Wallet, and Indexer.

Base URL

All paths are relative to the API host:
https://dev.api.withconvexity.com
Indexer, Products, Subscriptions, and Payments business endpoints are mounted under the /v1 prefix. Indexer endpoints additionally live under /v1/indexer.

Response envelope

Successful responses are wrapped in a consistent envelope:
{
  "status": true,
  "message": "Products retrieved successfully",
  "data": { }
}
FieldTypeDescription
statusbooleantrue on success, false on error.
messagestringHuman-readable summary of the result.
dataobject | array | nullThe payload. Shape depends on the endpoint.
Error responses use the same envelope with status: false and no data (some validation errors add an errors array). See Errors.

Content types

Send Content-Type: application/json on requests with a body, and Accept: application/json to receive JSON. All request and response bodies are JSON.

Pagination

Two pagination styles are used depending on the service. Both are documented per endpoint, but they fall into these shapes:
Page-based (Payments, Subscriptions, Products, Indexer). Request with page and pageSize (or limit) query parameters:
{
  "items": [ ],
  "total": 2,
  "page": 1,
  "pageSize": 20
}
Products and Indexer return a meta block instead of inline fields:
{
  "data": [ ],
  "meta": { "total": 1, "page": 1, "limit": 20, "totalPages": 1 }
}
Page-size limitsDefaults are page=1 and pageSize/limit=20. Maximums vary by service: Payments and Subscriptions cap at 100; Products caps at 200; Indexer caps at 200.

Data types & formats

TypeNotes
TimestampsISO 8601 UTC strings, e.g. 2026-06-17T10:20:08.000Z.
Monetary amounts (fiat)Integer major units unless noted — e.g. 1500 = ₦1,500.
Token amounts (on-chain)Strings in the token’s smallest unit (e.g. "1000000").
USD valuesDecimal strings, e.g. "15.871500".
IdentifiersUUIDs, Mongo ObjectIds, or integers depending on the resource.
AddressesHex strings (0x...) for EVM; base58 for Solana.
EnumsUppercase string constants (e.g. SUCCESS, MONTHLY, EVM).

Idempotency

Value-moving wallet operations require an Idempotency-Key request header so a retried request never executes twice:
EndpointHeader
Initiate transfer (POST /v1/wallet/transaction/)Idempotency-Keyrequired
Sign transaction (POST /v1/wallet/hd/sign)Idempotency-Keyrequired
Generate a unique key per operation (a UUID works well) and send it on the request:
curl -X POST https://dev.api.withconvexity.com/v1/wallet/transaction/ \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0c1d2e3f-4a5b-6c7d-8e9f-001122334455" \
  -d '{ "fromAddress": 0, "toAddress": "0x...", "amount": "1000000", "chainType": "EVM", "chainId": 8453 }'
If a request is retried with the same key — after a network timeout, for example — the server returns the original result instead of submitting a second transfer or signature. Reuse a key only when retrying the same operation; use a fresh key for each new one.
The exact key format, how long a key is retained, and the response when the header is missing follow standard (Stripe-style) idempotency semantics here. Confirm these details against your account’s configuration — this section will be tightened once the precise contract is verified.

Rate limiting

Endpoints are throttled. When you exceed a limit you receive 429 Too Many Requests:
{
  "status": false,
  "message": "Too many requests. Please try again later.",
  "retryAfter": 42
}
The retryAfter field (seconds) tells you when to retry. Back off and retry after that interval. The token endpoint is limited to 30 requests/minute/IP.