Quickstart

This guide gets you from zero to your first successful API call.

1. Get an API key

Self-service keys are issued from the customer dashboard: Settings → API. A key is bound either to your whole tenant or to a single customer/business, and carries one or more scopes. Ask for every scope the operations you will call require — the route-to-scope matrix is in Authentication & scopes; transactions:write does not cover payout batches. An IP allowlist is mandatory at creation.

Keys look like kp_live_0123456789abcdef.<secret>. The part before the dot is a public prefix you can log; the whole string is the credential.

If you don't have dashboard access yet, or need a scope the dashboard doesn't self-serve, contact your Kwiikpay account manager.

2. Make your first call: find out who you are

Every customer-scoped operation takes a customerId in its path. GET /api/v1/partner/me tells you yours, what the key is bound to, and which scopes it holds — and it needs no scope beyond a valid key, so it works on day one:

curl https://api.kwiikpay.io/api/v1/partner/me \
  -H "X-Api-Key: kp_live_..."
{
  "success": true,
  "status_code": 200,
  "message": "Identity retrieved successfully",
  "data": {
    "customer_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "subject_binding": "subject",
    "tenant_id": "9c1b2d3e-4f50-4a6b-8c7d-0e1f2a3b4c5d",
    "api_key_prefix": "kp_live_0123456789abcdef",
    "scopes": ["accounts:read", "accounts:write", "balances:read", "withdrawals:write"],
    "delegated_customer_ids": []
  }
}

customer_id is null for a tenant-wide key (it acts for every customer, so it must name one explicitly) and for a legacy unbound key (which authenticates but reaches no data — ask us to reissue it). Do not send an X-Tenant-Id header on this surface: it is refused with 400.

There is also GET /api/v1/partner/test, an older connectivity check. It requires onboarding:read and returns a bare object — { "success": true, "message": "API key authentication working!", "tenant_id": "…" }not the envelope every other v1 response uses. Do not model your client on it.

3. Read the envelope

Every /api/v1/partner response, success or refusal, is { success, status_code, message, data } with snake_case fields. Branch on the HTTP status (success and status_code merely repeat it), and on a 409/422 read data.code. Authentication, rate-limit and idempotency failures are not in the envelope: they are RFC 7807 application/problem+json. Errors has the full picture; /api/v2/public bodies are camelCase and use their own list envelope.

4. Which API surface should I use?

Kwiikpay currently runs two supported API generations side by side. They are parts of one customer integration, and it is normal to use both:

The same key authenticates both. A customer-dashboard key is normally subject-bound: both surfaces operate that Kwiikpay customer's resources. There is no announced end of life for either surface; see Versioning.

5. A first money-movement flow

For a parent operating on behalf of its own sub-customers, follow Sub-customers & parent access for the parent/child IDs and full flow.

  1. GET /api/v1/partner/customers/{customerId}/onboarding/status — money operations refuse a customer who has not reached an approved status.
  2. POST /api/v1/partner/customers/{customerId}/banking/accounts — open a fiat account (send an Idempotency-Key; every mutating call requires one).
  3. Register a webhook endpoint via POST /api/v2/public/webhook-subscriptions and react to deposit.received.
  4. POST /api/v1/partner/customers/{customerId}/banking/beneficiaries, then POST /api/v1/partner/customers/{customerId}/banking/withdrawals.

6. Next steps