Get started

Authentication

API keys, scopes, IP allowlists, rate limits and the response envelope.

API keys

Every request to https://deriapi.site/api/v2 needs a secret API key. Create keys under API keys in the dashboard. A key looks like this:

text
dpk_live_1a2b3c4d5e6f_<48 hex characters>

The part up to the second underscore (dpk_live_1a2b3c4d5e6f) is the public prefix. The dashboard shows it so you can tell keys apart. The full secret is shown once, when you create the key. Deripay stores only a hash of it, so a lost secret cannot be recovered. Create a new key and revoke the old one.

Send the key in the Authorization header:

http
GET /api/v2/ping HTTP/1.1
Host: deriapi.site
Authorization: Bearer dpk_live_1a2b3c4d5e6f_…

The X-API-Key: dpk_live_… header is also accepted. Prefer Authorization: Bearer.

All keys are live keys. There is no test mode.

Keep the key on your server

The key can start deposits and withdrawals for every customer you have connected. Treat it like a database password:

  • Call Deripay only from your backend. Your website or mobile app calls your backend.
  • Never ship the key in browser JavaScript, a mobile app binary, a public repository, logs or screenshots.
  • Store it in a secrets manager or a server environment variable such as DERIPAY_API_KEY.
  • If a key leaks, revoke it in the dashboard at once and create a new one.

Scopes

Each key has one or more scopes. A request with a key that lacks the scope fails with 403 AUTH_INSUFFICIENT_SCOPE.

Scope Allows
connections POST /connections, PATCH /connections/{id}/default-phone
deposits POST /deposits, POST /deposits/{id}/otp
withdrawals POST /withdrawals, POST /withdrawals/{id}/confirm, POST /withdrawals/{id}/resend
read GET /connections, GET /connections/{id}, GET /connections/{id}/balance, GET /transactions, GET /transactions/{id}, GET /transactions/{id}/events

GET /ping, GET /markets and GET /rates work with any valid key.

Give each server only the scopes it needs. For example, a reporting job needs only read.

IP allowlist

A key can be limited to a list of IP addresses (IPv4 or IPv6, up to 20). Set it when you create the key or later from the key's row in the dashboard. An empty list allows any IP.

A request from an address not on the list fails with 403 AUTH_IP_NOT_ALLOWED. The message names the IP Deripay saw, which helps when your server sits behind a NAT or proxy.

Rate limits

Limits apply per key, per route, over a 60 second window. When you go over, the response is 429 RATE_LIMITED with a Retry-After header in seconds.

Endpoint Requests per minute
POST /connections 30
POST /deposits 30
POST /deposits/{id}/otp 30
POST /withdrawals 20
POST /withdrawals/{id}/confirm 20
POST /withdrawals/{id}/resend 10
GET /transactions/{id}/events 60
Every other endpoint 120

Routes with an id in the path are counted per path, so polling two different transactions uses two separate budgets.

Some payment network checks also return 429, for example WITHDRAWAL_COOLDOWN. Those also carry Retry-After. See Errors.

Response envelope

Every JSON response has the same shape.

Success:

json
{
  "success": true,
  "data": { }
}

Error:

json
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Some fields are missing or invalid.",
    "details": [{ "field": "amount", "message": "Whole local currency units only" }],
    "request_id": "req_9f1c2b3a4d5e6f70"
  }
}
  • Branch on error.code. It is stable and machine readable.
  • Show or log error.message for people. Do not parse it.
  • error.details is present only on some errors. For INVALID_REQUEST it lists each failing field.
  • error.request_id identifies the request. Quote it when you contact support.

The full list of codes is in Errors.

Response headers

Header Value
X-Request-Id The request id, for example req_9f1c2b3a4d5e6f70. Sent on every response, including successes. Log it.
Deripay-Version v2 on JSON responses.
Cache-Control no-store.
Retry-After Seconds to wait. Sent with 429 responses and some others that ask you to wait.
Idempotent-Replayed true when a deposit or withdrawal request was a replay of an earlier one. See Idempotency.

Requests

  • Send JSON bodies with Content-Type: application/json. A body that is not valid JSON fails with 400 INVALID_REQUEST.
  • Field names are snake_case.
  • Ids are prefixed: con_ for connections and txn_ for transactions.
  • Timestamps are ISO 8601 in UTC.