Create a 0Gate session
POST /gate_sessions - Create a hosted session and return the browser-safe client secret once.
0Gate is the primary public integration path for hosted payment, ramp, and swap experiences. Keep secret-key operations on your server and hand only browser-safe values to the widget.
A session binds an amount and currency server-side, then hands the browser a one-time client_secret. The browser presents that secret to the embed bootstrap to frame the widget against this exact, locked session. Create the session from your server with a secret key; the user never sees your sk_*.
Endpoint
| Field | Value |
|---|---|
| Method | POST |
| Path | /v1/gate_sessions |
| Area | Sessions |
| Operation id | createSession |
| Auth boundary | Secret key from your server. |
The full request URL is https://gate-api.0bit.app/v1/gate_sessions.
Use it for
Create a hosted session and return the browser-safe client secret once.
Use this endpoint only for the partner-scoped resource it describes. Store your own reference id, the returned 0Bit object id, the request id, timestamps, and the current status so support and reconciliation do not depend on browser callbacks alone.
Production rules
- Keep secret keys on your server. This endpoint requires a
sk_*key. Apk_*publishable key is browser-only and used solely for the embed bootstrap. - Validate environment, mode, entitlement, asset, network, and amount before the call.
- Send an
Idempotency-Keyfor the logical write and retry timeouts with the same key. - Capture
client_secreton this create response — it is returned once and never appears on retrieve or list. - Branch on machine-readable status, error code, object id, and request id.
- Treat examples and placeholder ids as fake data only.
Request headers
| Header | Required | Use it for |
|---|---|---|
Authorization | Yes | Bearer sk_test_… or Bearer sk_live_…. The key's mode (test/live) is inherited by the session. |
Idempotency-Key | Yes | A UUID for this logical create. Repeats with the same key and body collapse to the original response. |
Content-Type | Yes | application/json. |
Idempotency protects retries
Send a fresh Idempotency-Key UUID per create and reuse the same key when you retry a timed-out request. The server returns the original session instead of creating a duplicate.
Request body
| Field | Required | Type | Use it for |
|---|---|---|---|
amount | Yes | decimal string | Positive amount, max 8 fractional digits. Bound to the session; later widget actions must match it exactly. Always a string, never a float. |
currency | Yes | string (ISO 4217) | Three-letter fiat code, for example EUR. Uppercased server-side. |
return_url | Yes | string (https URI) | Where the widget sends the user after a successful flow. HTTPS only (loopback allowed in dev); the URL's origin must be in your allowed_domains. |
cancel_url | No | string (https URI) | Where the widget sends the user on cancel. Same origin rules as return_url. |
target_token | No | string | Constrain the session to a single token, for example USDC. Uppercased server-side. |
target_network | No | string | Constrain the session to a single network, for example ETHEREUM. Uppercased server-side. |
flow | No | on_ramp/off_ramp/swap | Lock the widget to one flow and hide the buy/sell/swap tab strip. Omit for the legacy "open" widget where the user picks. |
wallet_address | No | string (≤128) | Pre-fill the destination wallet. Validated against the resolved network at flow time, not at create. |
user_reference | No | string (≤128) | Opaque partner-side id (your user id, order id, CRM record). Echoed in webhook payloads for correlation. |
metadata | No | object | Opaque per-session notes, returned verbatim. Not used for business logic. |
quote_preview_id | No | string (24-hex) | Id from POST /v1/quotes/preview. When supplied, amount/currency/asset/side must match the locked preview or the request is rejected. |
kyc_package | No (kyc_trusted partners only) | object | Partner-supplied pre-verified KYC. Contract-gated — only accepted when your partner record is kyc_trusted; otherwise 403 with code: kyc_package_not_trusted. The raw body is never echoed in any response. |
Money values are strings
amount is a decimal string, never a float (for example "100.00"). The bound amount is enforced on every later action against the session.
return_url must be an allowed origin
The origin of return_url (and cancel_url, if set) must already be listed in your allowed_domains. An origin that is not allowed is rejected — see the errors table below.
Response
On success the server returns HTTP 201 Created with the GateSession object plus a one-time client_secret.
Response fields
| Field | When present | Use it for |
|---|---|---|
id | Always | Server-assigned session id. Join session, transaction, and webhook records. |
object | Always | gate_session discriminator. |
partner_id | Always | The partner that owns the session. |
mode | Always | test or live, inherited from the sk_* that created it. |
amount | Always | The bound amount, as a decimal string. |
currency | Always | The bound, uppercased ISO 4217 code. |
return_url | Always | The success redirect you supplied. |
cancel_url | Always | The cancel redirect, or null. |
status | Always | Lifecycle state. A fresh session is open. |
expires_at | Always | ISO-8601 expiry, default 24h after creation. |
created_at | Always | ISO-8601 creation time, or null. |
flow | Always | The locked flow, or null for the open widget. |
target_token | Always | The token constraint, or null. |
target_network | Always | The network constraint, or null. |
wallet_address | Always | The pre-filled wallet, or null. |
user_reference | Always | Your opaque correlation id, or null. |
kyc_pre_verified | Always | true only when a kyc_trusted partner supplied an accepted kyc_package. |
metadata | Always | Your opaque notes, returned verbatim. |
client_secret | Create only | gsec_<id>_…. Hand to the browser for the embed bootstrap. Never returned again. |
Examples
curl -X POST https://gate-api.0bit.app/v1/gate_sessions \
-H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"amount": "100.00",
"currency": "EUR",
"return_url": "https://partner.example/checkout/done"
}'{
"id": "67a1f3b9e4b0c10001234567",
"object": "gate_session",
"partner_id": "507f1f77bcf86cd799439011",
"mode": "test",
"amount": "100.00",
"currency": "EUR",
"return_url": "https://partner.example/checkout/done",
"cancel_url": null,
"status": "open",
"expires_at": "2026-05-27T12:00:00.000Z",
"created_at": "2026-05-26T12:00:00.000Z",
"flow": null,
"target_token": null,
"target_network": null,
"wallet_address": null,
"user_reference": null,
"kyc_pre_verified": false,
"metadata": {},
"client_secret": "gsec_67a1f3b9e4b0c10001234567_AbCdEfGhIjKlMnOpQrStUvWxYz012345"
}Store client_secret now — it is never returned again. Hand it to the browser to bootstrap the embedded widget.
{
"id": "67a1f3b9e4b0c10001234999",
"object": "gate_session",
"partner_id": "507f1f77bcf86cd799439011",
"mode": "test",
"amount": "250.00",
"currency": "EUR",
"return_url": "https://partner.example/checkout/done",
"cancel_url": null,
"status": "open",
"expires_at": "2026-05-27T12:00:00.000Z",
"created_at": "2026-05-26T12:00:00.000Z",
"flow": "on_ramp",
"target_token": "USDC",
"target_network": "ETHEREUM",
"wallet_address": null,
"user_reference": "order_abc123",
"kyc_pre_verified": false,
"metadata": {},
"client_secret": "gsec_67a1f3b9e4b0c10001234999_ZyXwVuTsRqPoNmLkJiHgFeDcBa987654"
}A flow lock forces the widget into one flow and hides the tab strip; target_token/target_network constrain what the user can pick.
Errors
All errors use the unified envelope and carry an X-Request-Id response header. Branch on code/type/statusCode, not on the free-form message.
{
"type": "forbidden",
"code": "kyc_package_not_trusted",
"message": "Example forbidden error using fake data.",
"request_id": "req_test_000000000123",
"doc_url": null,
"statusCode": 403
}| Status | type | When it happens |
|---|---|---|
400 | invalid_request | Bad body — malformed amount, an unknown currency, a non-HTTPS return_url, a return_url/cancel_url whose origin is not in allowed_domains, or a quote_preview_id that is missing, expired, already used, or mismatched. |
401 | unauthorized | Missing or invalid secret key. |
403 | forbidden | Access denied. Branch on code: kyc_package_not_trusted (partner is not kyc_trusted), quota_exhausted (live keys only — session cap reached for the period; test mode is unmetered), or kit_blocks_not_enabled (a flow was sent but flow sessions are not enabled). |
429 | rate_limited | Throttled at 10 creates per minute per key. Back off and retry with the same Idempotency-Key. |
5xx | server_error | Transient server or upstream failure. Retry with bounded backoff and the same Idempotency-Key. |
Public boundary
This reference covers partner-scoped endpoint behavior, authentication, idempotency, webhook verification, and support-safe records. Internal operations, settlement venues, fiat-rail providers, KYC vendors, administrative routes, and unsupported availability claims are outside the public API contract.