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 prefix | Environment | Moves real money |
|---|---|---|
ck_test_ | Test (sandbox) | No |
ck_live_ | Live | Yes |
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:
| Header | Value |
|---|---|
x-api-key | your key |
x-timestamp | Unix time in milliseconds; must be within 5 minutes of Creddot's clock |
x-signature | hex 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}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')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.
| Permission | Allows |
|---|---|
collections:create | Checkout sessions, server-side collections |
transactions:read | Transaction lookup and listing |
wallets:read | Wallet balances |
virtual-accounts:read | Dedicated collection accounts |
payouts:create | Recipient validation and payouts |
bills:read, bills:create | Bill catalogue, validation and payment |
payment-links:read, payment-links:manage | Payment links |
invoices:read, invoices:manage | Invoices |
customers:read, customers:manage | Customers |
subscriptions:read, subscriptions:manage | Plans, subscriptions and subscribers |
refunds:read, refunds:create | Refund requests |
sandbox:simulate | Test-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.