Create a pay-in
POST /rails/pay_ins - Redeem an entitled signed quote into a pay-in 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-in is the money-shaped step that turns a locked, signed quote into a fiat collection from the session's KYC-approved user. You do not pass an amount, a currency, or a method here — they are read authoritatively from the quote you reference. Your server makes this call, stores the returned id and status, and tracks the rail to settlement.
Endpoint
| Field | Value |
|---|---|
| Method | POST |
| Path | /v1/rails/pay_ins |
| Area | Rails |
| Operation id | createPayIn |
| Auth boundary | Secret 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-in record and initiate the fiat collection.
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 apk_*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 and method come from the quote, not the request
amount, currency, and method are derived authoritatively from the locked quote (quote_id) and are not accepted in the request body. Any PII or payout-instruction field is rejected with 400. Collection details come from the verified user record, never from the partner request body.
Request headers
| Header | Required | Use it for |
|---|---|---|
Authorization | Yes | Bearer sk_* secret key from your server. |
Idempotency-Key | Yes | UUID for the logical write. Replaying the same key + body collapses to the original response. |
Content-Type | Yes | application/json. |
Request body
| Field | Required | Type | Use it for |
|---|---|---|---|
gate_session_id | Yes | string (max 64) | The session whose KYC-approved user the pay-in collects from. The 0Bit user is derived from this. |
quote_id | Yes | string (max 64) | The locked signed quote to redeem. amount, currency, and method are read from it. |
reference | No | string (max 128) | Your own free-form reference, echoed back on the record for reconciliation. |
metadata | No | object | Arbitrary 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_in object.
| Field | When present | Use it for |
|---|---|---|
object | Always | Constant rail_pay_in for client-side type narrowing. |
id | Always | The pay-in id. Pass it to GET /rails/pay_ins/{id}. |
kind | Always | Constant pay_in. |
status | Always | Lifecycle state: pending, processing, settled, failed, or cancelled. |
gate_session_id | Always | Echoes the session this pay-in belongs to. |
quote_id | Always | Echoes the redeemed signed quote. |
method | Always | The pay-in method derived from the quote. |
amount | Always | Signed, fee-inclusive amount the customer pays (base plus fees), as a decimal string. |
currency | Always | ISO 4217 fiat currency of amount. |
reference | Always | Your supplied reference, or null. |
created_at | Always | RFC 3339 timestamp the record was created. |
account_blocked | Conditional | true 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 pays (base plus 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_ins \
-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_9f8e7d6c5b4a",
"reference": "order_test_001"
}'{
"object": "rail_pay_in",
"id": "rpi_test_0a1b2c3d4e5f",
"kind": "pay_in",
"status": "pending",
"gate_session_id": "gs_test_67a1f3b9e4b0c10001234567",
"quote_id": "qt_test_9f8e7d6c5b4a",
"method": "bank_transfer",
"amount": "100.50",
"currency": "EUR",
"reference": "order_test_001",
"created_at": "2026-01-01T00:00:00Z"
}Store id and status, then poll GET /rails/pay_ins/{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
}| Status | type | When it happens |
|---|---|---|
400 | invalid_request | Missing gate_session_id/quote_id, a money or PII field in the body, or a malformed value. |
401 | unauthorized | Missing or invalid secret key. |
403 | forbidden | Credential rejected, rail access not enabled, mode mismatch, or the session belongs to another partner. |
404 | not_found | Session or quote does not exist or is not scoped to this credential. Cross-tenant access is 404. |
409 | conflict | The quote is already consumed or expired, or the rail conflicts with a prior state transition. |
429 | rate_limited | Request throttled. 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, administrative routes, settlement venues, and unsupported availability claims are outside the public API contract.