Introduction
Every call to the Bahn REST API must satisfy three requirements: a valid API key, a signed (or encrypted) request body, and idempotency headers. This page explains each requirement and what you need to set up before making your first call.
Base URLs
Send every request to the base URL for your target environment:
| Environment | Base URL | Use case |
|---|---|---|
| Sandbox | https://bn.cakedigibank.tech | Testing and development — no real payments. |
| Production | https://bn.cake.vn | Live payments. |
Before You Begin
During onboarding, complete the following steps once:
- Generate two P-256 key pairs — one for signing requests, one for decrypting responses. See Key Generation.
- Share both public keys with Bahn — your private keys never leave your systems.
- Receive your API key from Bahn.
API Key
Include your API key on every request using the Bn-Api-Key header:
Bn-Api-Key: <your-api-key>INFO
Your API key is issued once at onboarding. Keep it secure and never share it. If it is compromised, contact Bahn support to have it rotated.
Request Signing (JOSE)
For requests that carry a body, Bahn uses the JOSE framework to verify the integrity and confidentiality of data in transit.
The Bn-Jose-Method header is mandatory on all requests with a body. It tells Bahn how to interpret the payload:
| Bn-Jose-Method | Description |
|---|---|
jws | The body is signed with your private signing key. Bahn verifies it using your registered public key. |
jwe | The body is encrypted with Bahn's public key. Only Bahn can decrypt it. |
jws+jwe | The body is first signed (JWS), then the resulting token is encrypted (JWE). Provides both authenticity and confidentiality. |
Important
Currently, all API calls from merchants must use Bn-Jose-Method: jws. See JWS for the full signing workflow.
Content Types
Bahn accepts two serialization formats for the signed body:
application/jose — Compact Serialization
The JWS token as a dot-delimited string sent directly as the request body:
<base64url(header)>.<base64url(payload)>.<base64url(signature)>application/jose+json — JSON Serialization
The JWS General JSON Serialization as a JSON object:
{
"payload": "<base64url(payload)>",
"signatures": [
{
"protected": "<base64url(header)>",
"signature": "<base64url(signature)>"
}
]
}When using
application/jose+jsonwith multiple signatures, Bahn uses the first entry for verification.
Required JOSE Header Parameters
JWS
| Parameter | Description |
|---|---|
alg | Signature algorithm (e.g. ES256). |
kid | Key ID of the merchant's registered public signing key. |
url | The request endpoint path. Binds the token to this endpoint and prevents replay attacks. |
iat | Issued-at timestamp (Unix seconds). Allows Bahn to reject stale tokens. |
JWE
| Parameter | Description |
|---|---|
alg | Key management algorithm used to wrap the content encryption key. |
enc | Content encryption algorithm. |
kid | Key ID of Bahn's public encryption key used. |
Note
For jws+jwe, the JWS headers apply to the inner signing step and the JWE headers apply to the outer encryption step.
Public Key Requirements
When submitting your public keys to Bahn, each key must:
- Be in JWK (JSON Web Key) format.
- Include a
kid(Key ID) field — Bahn uses this to look up the correct key. - Include a
usefield set tosig(signing) orenc(encryption).
Idempotency
WARNING
Idempotency is currently enabled on select APIs only. Before relying on Bn-Idempotency-Key for a given endpoint, contact Bahn to confirm it is enabled for your account.
Two idempotency headers are required to prevent duplicate operations and enable safe retries:
| Header | Required on | Description |
|---|---|---|
Bn-Request-Id | All requests | A unique identifier for each individual request attempt. Generate a new value for every attempt, including retries. |
Bn-Idempotency-Key | All non-GET requests | A stable key representing the logical operation. If a request with this key has already succeeded, Bahn returns the cached response without executing the operation again. |
Bn-Request-Id: 7f3e9c1a-4b2d-4e8f-a1c0-123456789abc
Bn-Idempotency-Key: order_001_create_paymentTIP
Use a deterministic value for Bn-Idempotency-Key — such as your internal order ID — so that retries caused by network failures or timeouts always carry the same key and never result in duplicate charges.
Next Steps
- Generate Key Pairs — create and export your P-256 signing and encryption key pairs.
- Make Your First Request — sign and send a request end-to-end with a Go example.
- JSON Web Signature — deep dive into the JWS signing workflow.