Credentials
Every customer operation is authenticated with an API key and nothing else. Session credentials are rejected: these routes are API-key only.sk_test_… key against the live host fails with 401 INVALID_API_KEY, and so does the reverse — the failure is deliberately indistinguishable from an invalid key.
Prerequisites the service checks
Two checks run before any customer work happens, in this order:- The client exists. If the key authenticates but its business has been removed, you get
404 client_not_found. - The client is a business. Customer management is a business-client feature; anything else gets
409 client_not_a_business.
Environments
Sandbox and live are separate deployments with separate databases. A customer created in sandbox does not exist in live, and identifiers do not carry across.Rate limits
Limits are per 60-second window and are counted twice for each request — once against your business, once against the individual key. Both must pass.
Two further limits apply to every authenticated request regardless of route: 300 per minute per source IP, and 1,200 per minute per credential.
Exceeding any of them returns
429 with retryAfterSeconds in the body. There is no Retry-After header yet — read the body. See rate limits for backoff guidance.
Bulk import arithmetic follows directly: at 120 writes per minute, ten thousand customers takes about 83 minutes at a steady rate. Pace the job rather than absorbing 429s.
Webhooks
Customers emit two events, both carrying the complete customer object as theirdata:
Archiving emits nothing.
Verification outcomes arrive as
customer.kyc.approved, customer.kyc.rejected and customer.kyc.suspended, each carrying the customer object plus a kyc object. They follow the verification for as long as it exists, so the same customer can send more than one. See Identity and verification.
Three things to get right in the receiver:
- Deduplicate on the
Sakawave-Webhook-Idheader. The body has onlyeventanddata; there is no ID inside it. - The event payload is a snapshot, not a delta. It tells you the customer’s state at that moment, not what changed. If you need the diff, compare against your own copy.
- Do not treat the event as the source of truth. Delivery is a single attempt with manual resend and no automatic retry. Reconcile by listing customers.
Request identifiers
SendX-Request-ID on every call. It comes back on the response and is the fastest way for support to find your request. If you omit it, or send something malformed, Sakawave generates one.
Configuration checklist
- Sandbox and live keys stored in a secrets manager, never in source control
- Base URL configured per environment, never hardcoded per call site
-
externalReferencechosen from a stable identifier in your own system - Write throughput paced under 120 per minute
-
X-Request-IDset from your own trace or correlation ID - Webhook endpoint configured separately in each environment, deduplicating on the header ID
- Error handling branches on
code, never onmessage