Authentication
Two profiles — v1-static (default) and v2-hmac (HMAC-signed, required for high-volume partners)
The Bold MFB API supports two authentication profiles. Each Business is configured server-side to use one or the other; partners do not switch profiles per request.
Choosing a profile
| Profile | Use when |
|---|---|
v1-static | Default for merchants and standard integrations. Static (api_key, api_secret) pair sent on every request. Matches the historical Kele convention. |
v2-hmac | Required for high-volume / high-security partner integrations. Requests are signed with an HMAC-SHA256 derived from the partner secret. The secret never leaves the partner; only the signature is on the wire. |
Operations configure the profile per Business at onboarding. If you are unsure which profile your tenant uses, ask Kele Operations.
Profile v1-static
Static credential pair. Both values are obtained from the API settings page in the Kele dashboard.
| Header | Value |
|---|---|
x-api-key | Partner public key (pk_live_… in production, pk_test_… in sandbox). |
x-api-secret | Partner secret. |
The public key remains static. The secret key undergoes periodic rotation — best practice is every 30 to 90 days. The secret key cannot be recovered after the first display; copy it immediately on creation.
Obtaining keys
Navigate to the API settings page in the Kele dashboard and click Generate. First-time users receive a one-time public key and secret key. Subsequent rotations issue a new secret while the public key persists.
Profile v2-hmac
The api_secret never leaves the partner. Each request carries a SHA-256 HMAC of a canonical string that includes the timestamp, method, path, and raw body.
Headers
Every request must carry these three headers:
| Header | Value |
|---|---|
x-api-key | Partner public key (pk_live_… in production, pk_test_… in sandbox). |
x-timestamp | Unix seconds at the time of request. Server enforces a ±5-minute window. |
x-signature | lowercase(hex(HMAC-SHA256(secret, canonical_string))) — see below. |
Content-Type: application/json for any request with a body.
Canonical signing string
Five dot-separated segments. Empty segments are still represented by their delimiting dots — a GET with no query and no body ends in ...
canonical_query is the request’s query parameters, sorted lexicographically by key and re-encoded with RFC-3986 percent-encoding (space as %20, not +). When there are no query parameters this segment is the empty string. The exact bytes you sign for the query must also be the exact bytes on the wire — if your HTTP client re-orders or re-encodes them, the signature will not verify.
Three things to watch for:
- Path is the URL path component only, with the leading
/apiprefix included. For example, sign/api/outlets, nothttps://corebanking.boldmfb.com/api/outlets?status=ACTIVEand not/outlets. The query goes into its own segment, not the path. - Query is part of the signature. Different query parameters produce different signatures, so two GETs to the same path with different params in the same second do not collide. The replay cache is keyed on
(api_key, signature)— only an exact retransmission of the same request triggersREPLAY_DETECTED. - Raw body is the exact bytes you transmit. If your HTTP client re-serialises the JSON in a different order between signing and sending, the signature will mismatch. For a
GETwith no body, the body segment is the empty string and the trailing dot is still present.
Reference signers
Each tab below is a complete, copy-pasteable signer that builds the canonical string, computes the HMAC, and sends the request with the three required headers. Drop it into your project, set the three env vars (KELE_BASE, KELE_API_KEY, KELE_PARTNER_SECRET), and replace the example call at the bottom with your own.
Two things to verify in your client before you trust it end-to-end:
- The serialised body you sign is the exact bytes you transmit. Most HTTP clients will faithfully forward a string body, but middleware (proxies, logging hooks, body parsers that re-stringify) can silently re-encode JSON and break the signature.
- A repeated request with the same timestamp returns
401 REPLAY_DETECTEDon the second call. If it doesn’t, your shared-state cache (Redis on our side) is misbehaving — escalate.
Secret rotation
Partners rotate partner_secret with a 7-day overlap window. During the overlap the server accepts both the current and the previous secret, so the partner can deploy the new secret at its own cadence within those seven days.
Rotation is initiated by Kele Operations. After rotation, you receive the new plaintext secret out-of-band; the previous one continues to sign valid requests for 7 days from partner_secret_rotated_at.
If a leaked secret needs to be killed immediately, Kele Operations performs a compromise rotation: the previous secret is not populated, so the old secret stops working the instant the new one is installed.
Common 401 errors
| Symptom | Likely cause |
|---|---|
SIGNATURE_INVALID | Wrong secret, wrong canonical string, or body bytes mutated by a proxy |
TIMESTAMP_OUT_OF_WINDOW: clock skew exceeds 5 minutes | Local clock drift; sync to NTP |
TIMESTAMP_OUT_OF_WINDOW: x-timestamp must be unix seconds | You sent ms or a non-numeric value |
REPLAY_DETECTED | A request with this (api_key, signature) pair was already seen within the 600-second replay window. Change the timestamp |
AUTH_PROFILE_MISMATCH: this partner requires HMAC signed requests | You sent only x-api-secret; switch to the HMAC triplet |
Partner access has been disabled | Kele Operations has temporarily blocked the tenant. Contact support |
Sandbox keys cannot be used in production / Live keys cannot be used outside production | Wrong env or wrong key prefix |
Environment-scoped keys (both profiles)
API keys are environment-scoped. Sandbox keys (pk_test_*) cannot be used against live, and live keys (pk_live_*) cannot be used outside production. The middleware rejects mismatched env keys before any further processing.