0Bit Documentation

Errors

Handle validation errors, auth failures, state conflicts, rate limits, retryable failures, request ids, and idempotent writes.

Error handling is part of the API contract. A production integration should branch on machine-readable status and error fields, preserve request ids, retry only when the failure is retryable, and use idempotency keys for state-changing writes.

Error envelope

Examples in the source use a common error shape:

{
  "type": "invalid_request",
  "code": "invalid_request",
  "message": "Example validation or state error using fake data.",
  "request_id": "req_test_000000000123",
  "doc_url": null,
  "statusCode": 400
}

Treat code, type, statusCode, and request_id as integration signals. Do not build business logic by parsing the free-form message. Every response also carries an X-Request-Id header that mirrors request_id; capture it from headers even when there is no JSON body to parse.

Status classes

StatusMeaningRetry behavior
400Request shape, validation, or state input problem.Do not retry unchanged.
401Missing or invalid authentication.Do not retry until credentials are fixed.
402Insufficient balance to reserve or settle the write.Fund the balance, then retry.
403Valid credential but missing permission, entitlement, origin, or trusted status.Do not retry until access/config changes.
404Object not found or not partner-scoped.Check ids and ownership; do not expose foreign ids.
409State conflict, duplicate, expired, consumed, or already terminal object.Retrieve current state and branch.
429Rate limit.Retry with backoff and respect retry guidance.
501Capability not enabled for public use (for example, an off-ramp transact).Do not retry; request enablement through account review.
5xxServer or upstream failure.Retry bounded with the same idempotency key for writes.

Error types

type is a fixed, machine-readable classification of the failure. Branch on it for broad handling, and on code for specific cases.

typeTypical statusMeaning
invalid_request400Request shape, validation, or state input problem.
unauthorized401Missing or invalid authentication.
forbidden403Valid credential but missing permission or entitlement.
not_found404Object not found or not partner-scoped.
conflict409State conflict, duplicate, expired, consumed, or idempotency mismatch.
rate_limited429Velocity or throttle limit reached.
server_error5xxServer or upstream failure.

Cross-tenant lookups return 404, not 403

A lookup for an object that belongs to another partner returns 404, not 403. The API never confirms the existence of objects outside your own scope. Do not infer ownership or existence from the status, and do not surface foreign ids.

0Pools 403 denial codes

When a 0Pools request is rejected for access reasons, branch on the code field. The message is free-form and may change; the code is stable.

codeMeaningWhat to do
pools_not_enabled0Pools is not enabled for this partner.Request enablement through account review.
pool_access_suspendedThe partner's pool access is suspended.Contact 0Bit; access is operator-provisioned.
kyc_not_approvedKYC is not in an approved state.Wait for approval; do not retry on the same state.
pool_not_allowedThe pool is not in the partner's allowed set.Use a pool from GET /pools.
key_mode_mismatchThe key mode does not match the operation (for example, a publishable key on a secret-only route).Use the correct key for the operation.

Branch on code, not message

Drive logic from code, never the human-readable message. Messages are for logs and operators; codes are the stable contract. The 0Pools balance and capability responses deliberately omit access and KYC state — those surface only as these 403 denial codes.

Idempotent retry pattern

const idempotencyKey = order.storedIdempotencyKey;

const response = await fetch(`${process.env.OBIT_GATE_BASE_URL}/gate_sessions`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.OBIT_GATE_SECRET_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': idempotencyKey,
  },
  body: JSON.stringify({
    amount: '100.00',
    currency: 'EUR',
    return_url: 'https://partner.example/complete',
  }),
});

If the network fails after the server created state, retry with the same key. A new key may create a duplicate logical write.

Failure handling table

FailureWhat to logWhat to do
Validation errorRequest id, endpoint, schema field, safe partner reference.Fix request or user input.
Auth errorRequest id, key prefix, environment, endpoint.Rotate or correct credentials; do not log the full key.
Permission errorRequest id, product, entitlement, origin, environment.Request access or fix allow-list/config.
ConflictRequest id, object id, current known status.Retrieve current object and branch.
Rate limitRequest id, endpoint, key/environment, retry time.Back off and alert if sustained.
TimeoutIdempotency key, endpoint, object reference.Retry with same key and then read current state.
Webhook failureEvent id, delivery id, last response status.Fix endpoint and replay only after dedupe is in place.

Operational rules

  • Persist request ids in logs.
  • Persist idempotency keys for writes.
  • Persist event ids for webhooks.
  • Use decimal strings for money-like values where the API expects strings.
  • Do not depend on undocumented fields.
  • Use fake values in docs, tests, and screenshots.
  • Keep secrets, PII, provider payloads, and internal runbooks out of public docs and logs.

On this page