CreddotDocsCreddot Docs

Authentication

API keys, secrets, permissions and the headers every request needs.

API keys

Create keys in the dashboard under Settings, API Keys and Webhooks. Each key belongs to one environment:

Key prefixEnvironmentMoves real money
ck_test_Test (sandbox)No
ck_live_LiveYes

A key comes with an API secret that is shown once. Keep both on your server. If a secret leaks, revoke the key in the dashboard and create a new one.

Sending the key

Send the key and secret as headers on every request, over HTTPS:

curl https://api.creddot.com/api/v1/wallets \
  -H "x-api-key: ck_test_..." \
  -H "x-api-secret: ..."

Authorization: Bearer <secret> works in place of x-api-secret if your HTTP client prefers it.

Signed requests (optional)

Instead of sending the secret, you can sign each request with it. This keeps the secret off the wire entirely:

HeaderValue
x-api-keyyour key
x-timestampUnix time in milliseconds; must be within 5 minutes of Creddot's clock
x-signaturehex HMAC-SHA256, keyed with your secret, of the string below
{timestamp}.{METHOD}.{path and query}.{idempotency key or empty}.{hex HMAC-SHA256 of the JSON body, keyed with your secret}
Node.js
import { createHmac } from 'node:crypto';

const hmac = (data) => createHmac('sha256', process.env.CREDDOT_API_SECRET).update(data).digest('hex');

function signedHeaders(method, path, body, idempotencyKey = '') {
  const timestamp = Date.now().toString();
  const bodyHash = hmac(JSON.stringify(body ?? {}));
  const signature = hmac([timestamp, method.toUpperCase(), path, idempotencyKey, bodyHash].join('.'));
  return { 'x-api-key': process.env.CREDDOT_API_KEY, 'x-timestamp': timestamp, 'x-signature': signature, ...(idempotencyKey ? { 'x-idempotency-key': idempotencyKey } : {}) };
}
// path includes /api/v1, e.g. signedHeaders('POST', '/api/v1/payouts', body, 'payout-881')
Sign the exact JSON you send. Serialise the body once and reuse the same string for the hash and the request.

Permissions

Each key only does what its permissions allow. Give every integration the smallest set it needs. A request without the right permission gets 403.

PermissionAllows
collections:createCheckout sessions, server-side collections
transactions:readTransaction lookup and listing
wallets:readWallet balances
virtual-accounts:readDedicated collection accounts
payouts:createRecipient validation and payouts
bills:read, bills:createBill catalogue, validation and payment
payment-links:read, payment-links:managePayment links
invoices:read, invoices:manageInvoices
customers:read, customers:manageCustomers
subscriptions:read, subscriptions:managePlans, subscriptions and subscribers
refunds:read, refunds:createRefund requests
sandbox:simulateTest-mode simulation endpoints

IP allow-list

In the dashboard you can restrict each environment to the IP addresses of your servers. Requests from other addresses are rejected with 401, even with a valid key.

Rate limits

Each client can make about 120 requests a minute. Above that you get 429; wait and retry with backoff.

On this page