Authentication & signing
Base URL and format
- Endpoint:
https://api.cobrex.com - Format: requests and responses are JSON (
Content-Type: application/jsonwhere a body exists). - Keys: created in dashboard settings.
HTTP status codes
| Range | Meaning |
|---|---|
| 200 | Success (in Cobrex docs, success is usually 200). |
| 4xx | Client error: signature, parameters, permissions, not found. |
| 5xx | Server error; retry later if appropriate. |
Required headers
Every protected request must include:
1. x-uid or x-mid
x-uid— user id (u-…). Use for account-level operations.x-mid— merchant id (m-…). Use for merchant-context operations (e.g. payout from the merchant-linked account).
Send exactly one of these, depending on the flow.
2. x-timestamp
Current time as whole seconds since 1970-01-01 UTC (Unix time). Reduces replay risk; the server may reject stale or far-future timestamps.
const timestampSec = Math.floor(Date.now() / 1000);
Do not use raw Date.now() — those are milliseconds and will not match the expected signature.
3. x-signature
Hex HMAC-SHA256 of the canonical string (below), keyed with your API secret.
Building the string to sign (step by step)
- Full request URL — exactly as you call the API:
https+://+ host + path + query string (if any).
Query parameter order must match the outgoing request. - Line feed LF
\n. - Seconds only — the same value you send in
x-timestamp. - If the request has a body (e.g. JSON
POST):\n- Raw body — the exact bytes sent (after
JSON.stringifyor equivalent).
Whitespace and key order must match the real body.
If there is no body (typical GET): stop after step 3. Do not add an extra \n for an “empty body”.
POST example
Canonical string (three segments separated by \n):
https://api.cobrex.com/wallet
1752675847
{"asset":["USDT","TRX"],"network":"TRON","client":"test1","callback":"https://api.cobrex.com/webhook"}
GET example
https://api.cobrex.com/payment/p-1a9a67a1-46ce-11f1-8b35-7cc255316480
1752675847
Computing the hex signature in code
Same idea as CryptoJS / Postman snippets, without tying to a tool:
- Build
canonicalStringas above. - HMAC-SHA256 over
canonicalStringwith API secret. - Encode digest as hex (lowercase is typical for comparison).
Node.js (crypto):
const crypto = require('crypto');
function cobrexRequestSignature(canonicalString, apiSecret) {
return crypto.createHmac('sha256', apiSecret).update(canonicalString).digest('hex');
}
Use any vetted HMAC-SHA256 implementation elsewhere; the digest must match when the canonical string is identical.
Common mistakes
| Issue | Effect |
|---|---|
Milliseconds in x-timestamp | Signature mismatch. |
| Different JSON key order or spacing | Different body → different signature. Serialize once; reuse for body and signing. |
| URL missing query or wrong param order | Canonical string differs from server. |
Extra \n when there is no body | Signature mismatch. |
Webhooks: verifying inbound requests
Cobrex calls your URL when a payment or payout status changes. The body is JSON (payment object or payout object).
Option A — IP allowlist
Only accept traffic from Cobrex IPs:
46.166.162.83
(Infrastructure may change — confirm the live list with support before production.)
Option B — x-signature header
On your side:
-
Read the raw HTTP body as text/buffer before
JSON.parse(byte identity matters). -
Parse JSON to
datafor business logic. -
Expected signature per Cobrex webhook rules:
expected = HMAC-SHA256( JSON.stringify(data), api_secret ).digest('hex')Use the secret from the dashboard (or a dedicated webhook secret if Cobrex issues one — confirm with support).
Often it is more reliable to compute HMAC over the raw body string so you do not depend on re-stringifying JSON:
const crypto = require('crypto');const expected = crypto.createHmac('sha256', apiSecret).update(rawBodyString).digest('hex'); -
Compare
expectedto thex-signatureheader using constant-time comparison.
Next: accounts & balances, payments, payouts.