0Bit Documentation

Create a pay-out

POST /rails/pay_outs - Redeem an entitled signed quote into a pay-out record.

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.

Creating a pay-out is the money-shaped step that turns a locked, signed quote into a fiat disbursement to the session's KYC-approved user. You do not pass an amount, a currency, a method, or payout instructions here; they are read authoritatively from the quote and the verified user record. Your server makes this call, stores the returned id and status, and tracks the rail to settlement.

Endpoint

FieldValue
MethodPOST
Path/v1/rails/pay_outs
AreaRails
Operation idcreatePayOut
Auth boundarySecret key from your server.

This endpoint requires account-gated rail access. The 0Bit user is derived from the referenced session, never from the partner.

Use it for

Redeem an entitled signed quote into a pay-out record and initiate the fiat disbursement.

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 an sk_* key — never a pk_* publishable key.
  • Validate environment, mode, entitlement, asset, network, and amount before the call.
  • Send an Idempotency-Key (UUID) for the logical write and retry timeouts with the same key.
  • Branch on machine-readable status, error code, object id, and request id.
  • Treat examples and placeholder ids as fake data only.

Amount, method, and destination come from verified records

amount, currency, and method are derived authoritatively from the locked quote (quote_id) and are not accepted in the request body. Payout instructions come from the verified user record, never from the partner request body. Any PII or payout-instruction field is rejected with 400.

Request headers

HeaderRequiredUse it for
AuthorizationYesBearer sk_* secret key from your server.
Idempotency-KeyYesUUID for the logical write. Replaying the same key + body collapses to the original response.
Content-TypeYesapplication/json.

Request body

FieldRequiredTypeUse it for
gate_session_idYesstring (max 64)The session whose KYC-approved user the pay-out disburses to. The 0Bit user is derived from this.
quote_idYesstring (max 64)The locked signed quote to redeem. amount, currency, and method are read from it.
referenceNostring (max 128)Your own free-form reference, echoed back on the record for reconciliation.
metadataNoobjectArbitrary key/value pairs stored alongside the record.

No money or PII fields in the body

Do not send amount, currency, method, or any PII field. They are derived from the signed quote and the KYC record; supplying them is a 400.

Response

Returns 201 with a rail_pay_out object.

FieldWhen presentUse it for
objectAlwaysConstant rail_pay_out for client-side type narrowing.
idAlwaysThe pay-out id. Pass it to GET /rails/pay_outs/{id}.
kindAlwaysConstant pay_out.
statusAlwaysLifecycle state: pending, processing, settled, failed, or cancelled.
gate_session_idAlwaysEchoes the session this pay-out belongs to.
quote_idAlwaysEchoes the redeemed signed quote.
methodAlwaysThe pay-out method derived from the quote.
amountAlwaysSigned, fee-inclusive amount the customer receives (base minus fees), as a decimal string.
currencyAlwaysISO 4217 fiat currency of amount.
referenceAlwaysYour supplied reference, or null.
created_atAlwaysRFC 3339 timestamp the record was created.
account_blockedConditionaltrue when this rail pushed the user past the cumulative volume cap; the account is blocked for future rails pending manual review.

Amounts are strings

amount is the signed, fee-inclusive value that settles — what the customer receives (base minus fees). It equals the quote's fiat_pay_or_receive, not the fee-exclusive base. Always a decimal string, never a float.

Examples

curl -X POST https://gate-api.0bit.app/v1/rails/pay_outs \
  -H "Authorization: Bearer sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "gate_session_id": "gs_test_67a1f3b9e4b0c10001234567",
    "quote_id": "qt_test_1a2b3c4d5e6f",
    "reference": "withdrawal_test_001"
  }'
{
  "object": "rail_pay_out",
  "id": "rpo_test_6f5e4d3c2b1a",
  "kind": "pay_out",
  "status": "pending",
  "gate_session_id": "gs_test_67a1f3b9e4b0c10001234567",
  "quote_id": "qt_test_1a2b3c4d5e6f",
  "method": "bank_transfer",
  "amount": "98.75",
  "currency": "EUR",
  "reference": "withdrawal_test_001",
  "created_at": "2026-01-01T00:00:00Z"
}

Store id and status, then poll GET /rails/pay_outs/{id} or consume webhooks to follow the rail to settled.

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": "invalid_request",
  "code": "invalid_request",
  "message": "Example validation error using fake data.",
  "request_id": "req_test_000000000123",
  "doc_url": null,
  "statusCode": 400
}
StatustypeWhen it happens
400invalid_requestMissing gate_session_id/quote_id, a money or PII field in the body, or a malformed value.
401unauthorizedMissing or invalid secret key.
403forbiddenCredential rejected, rail access not enabled, mode mismatch, or the session belongs to another partner.
404not_foundSession or quote does not exist or is not scoped to this credential. Cross-tenant access is 404.
409conflictThe quote is already consumed or expired, or the rail conflicts with a prior state transition.
429rate_limitedRequest throttled. Back off and retry with the same Idempotency-Key.
5xxserver_errorTransient 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, administrative routes, settlement venues, and unsupported availability claims are outside the public API contract.

On this page