Orbita API reference

Everything you need to accept deposits, send payouts and react to events — with request examples in cURL, Node.js, Python and PHP.

Base URL https://api.orbitapay.dev/v2
API v2 · 2026-09-01 REST · JSON All systems operational

Introduction

Getting started

The Orbita API is organised around REST. It accepts JSON request bodies, returns JSON responses and uses standard HTTP verbs, status codes and authentication. Every account gets a sandbox and a live environment with separate keys, so you can build and test without moving real money.

  1. 1
    Create a sandbox account

    Sign up in two minutes. Sandbox keys are issued instantly — no compliance review needed.

  2. 2
    Make your first test payment

    Call Create a payment with any amount and an instant_bank method.

  3. 3
    Listen for webhooks

    Register an HTTPS endpoint and confirm you receive payment.approved.

  4. 4
    Go live

    Swap sk_test_ for sk_live_ keys once your merchant review is approved.

Environments

EnvironmentBase URLNotes
Sandboxhttps://sandbox.orbitapay.dev/v2Test methods in every market, no real money
Livehttps://api.orbitapay.dev/v2Requires an approved merchant account

Sandbox scenarios

Use the minor-unit amount to trigger specific outcomes. Everything else behaves exactly like production, including webhooks and routing decisions.

Amount ends inResultWebhook
…00Approvedpayment.approved
…51Soft decline, cascadedpayment.approved
…523-D Secure challengepayment.requires_action
…99Hard declinepayment.declined
Versioning

Pin a version with the Orbita-Version header. The current version is 2026-09-01. We never ship breaking changes to a pinned version, and new versions are announced 90 days ahead.

Introduction

Authentication

Authenticate every request with a secret API key passed as a bearer token. Keys are scoped to one environment and can be rolled at any time from Dashboard → Developers → API keys.

PrefixUsed for
sk_test_Server-side requests in the sandbox
sk_live_Server-side requests in production
pk_live_The cashier SDK in browsers and apps
whsec_Verifying webhook signatures

Send an Idempotency-Key header with every POST. Retrying with the same key returns the original response instead of creating a duplicate payment; keys are stored for 24 hours.

Authenticated request
curl https://api.orbitapay.dev/v2/balance \
  -H "Authorization: Bearer sk_test_9Qm2LwX8rT4vK7pN" \
  -H "Orbita-Version: 2026-09-01"
Keep secret keys on your server

Never ship sk_live_ keys in a mobile app, a browser bundle or a public repository. If a key leaks, roll it immediately — the old key stops working within 60 seconds.

Core resources

Create a payment

POST/v2/payments

Creates a deposit and returns the next action for the player — a redirect, a 3-D Secure challenge or an immediate approval. Orbita picks the route automatically unless you pin one.

Body parameters

  • amountintegerRequired

    Amount in minor units, e.g. 25000 for €250.00.

  • currencystringRequired

    Three-letter ISO 4217 code, e.g. EUR, BRL.

  • methodenumRequired

    One of card, instant_bank, ewallet, mobile_money, voucher, crypto.

  • customerobjectRequired

    Your player reference: id, plus country and email for better routing and risk scoring.

  • routingobject

    strategy: smart (default), cost or pinned with an acquirer id.

  • return_urlstring

    Where the player lands after a redirect or challenge.

  • metadataobject

    Up to 20 key-value pairs, returned on every event.

curl https://api.orbitapay.dev/v2/payments \
  -H "Authorization: Bearer sk_test_9Qm2LwX8rT4vK7pN" \
  -H "Idempotency-Key: dep_01J9ZK4T8M" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 25000,
    "currency": "EUR",
    "method": "instant_bank",
    "customer": { "id": "plr_7Hq2xK", "country": "DE" },
    "routing": { "strategy": "smart" },
    "return_url": "https://play.example.com/cashier/done"
  }'
201 CreatedResponse
{
  "id": "pay_3Kd8Wq2LmZ",
  "object": "payment",
  "status": "requires_action",
  "amount": 25000,
  "currency": "EUR",
  "method": "instant_bank",
  "customer": { "id": "plr_7Hq2xK", "country": "DE" },
  "route": {
    "provider": "a2a_de_02",
    "strategy": "smart",
    "score": 0.97
  },
  "next_action": {
    "type": "redirect",
    "url": "https://pay.orbitapay.dev/r/3Kd8Wq2LmZ"
  },
  "risk": { "score": 8, "level": "low" },
  "created": 1759484400,
  "livemode": false
}

Payment statuses

  • pending

    Created, waiting for the player or the rail.

  • requires_action

    Redirect or 3-D Secure challenge needed.

  • approved

    Funds authorised — credit the player's balance.

  • declined

    Final decline after all cascade attempts.

Core resources

Payouts

POST/v2/payouts

Sends a withdrawal to a player's bank account, wallet or crypto address. KYC, limits and AML screening run before the money moves; you get the result synchronously or through payout.* webhooks.

Body parameters

  • amountintegerRequired

    Amount in minor units.

  • currencystringRequired

    ISO 4217 code of the destination account.

  • destinationobjectRequired

    type is bank_account, wallet or crypto_address, plus the fields for that type.

  • speedenum

    instant (default where available) or standard.

  • referencestring

    Your withdrawal id, shown on the player's statement where supported.

GET/v2/payouts/{id}Retrieve a payout
curl https://api.orbitapay.dev/v2/payouts \
  -H "Authorization: Bearer sk_test_9Qm2LwX8rT4vK7pN" \
  -H "Idempotency-Key: wd_01J9ZM2Q4R" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 125000,
    "currency": "EUR",
    "speed": "instant",
    "customer": { "id": "plr_7Hq2xK" },
    "destination": {
      "type": "bank_account",
      "iban": "DE89370400440532013000",
      "holder_name": "Lena Hoffmann"
    },
    "reference": "W-48213"
  }'
201 CreatedResponse
{
  "id": "po_8Vn2Kx4TqM",
  "object": "payout",
  "status": "sent",
  "amount": 125000,
  "currency": "EUR",
  "speed": "instant",
  "rail": "eu_instant",
  "estimated_arrival": "2026-10-03T14:02:13Z",
  "reference": "W-48213",
  "created": 1759500131
}
Instant where it exists, fastest rail everywhere else

Instant payouts are available in 42 markets. If the destination bank can't receive instant transfers, Orbita falls back to the fastest available rail and tells you in payout.updated.

Events

Webhooks

Orbita sends events to your HTTPS endpoint as JSON POST requests. Respond with any 2xx status within 10 seconds; failed deliveries are retried with exponential back-off for 72 hours and can be replayed from the dashboard.

Common events

EventSent when
payment.approvedFunds are authorised and can be credited
payment.declinedFinal decline after all cascades
payment.requires_actionThe player must finish a redirect or challenge
payout.sentThe payout was handed to the rail
payout.failedThe destination rejected the payout
chargeback.openedAn issuer raised a dispute
settlement.paidA settlement batch reached your account
Example event
{
  "id": "evt_5Rm9Lq2Wz8",
  "type": "payment.approved",
  "created": 1759484402,
  "livemode": false,
  "data": {
    "object": {
      "id": "pay_3Kd8Wq2LmZ",
      "status": "approved",
      "amount": 25000,
      "currency": "EUR",
      "route": { "provider": "a2a_de_02", "attempts": 1 }
    }
  }
}

Verifying signatures

Every request carries an Orbita-Signature header with a timestamp t and an HMAC-SHA256 signature v1 of t + "." + raw_body, signed with your endpoint's whsec_ secret.

HeaderOrbita-Signature: t=1759484402,v1=6f1c2b0e9a7d44c3b8e5f2a1d0c9b8a7e6f5d4c3b2a1908f7e6d5c4b3a291807
import crypto from "node:crypto";

const TOLERANCE = 300; // seconds

export function verifyOrbitaSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((kv) => kv.split("=")));
  const age = Math.floor(Date.now() / 1000) - Number(parts.t);
  if (age > TOLERANCE) throw new Error("Timestamp outside tolerance");

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");

  const valid = crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(parts.v1, "hex"));
  if (!valid) throw new Error("Invalid signature");
  return JSON.parse(rawBody);
}
Verify against the raw request body

Parsing and re-serialising the JSON changes whitespace and key order and will break the signature. Reject events older than 5 minutes to protect against replay attacks.

Reference

Errors

Orbita uses conventional HTTP status codes. Codes in the 2xx range mean success, 4xx mean the request failed given the information provided, and 5xx are rare errors on our side that are always safe to retry with the same idempotency key.

StatusMeaning
200OK — the request succeeded.
201Created — a new payment or payout was created.
400Bad request — a parameter is missing or malformed.
401Unauthorized — no valid API key was provided.
402Request failed — valid request, but the payment was declined.
404Not found — the resource doesn't exist.
409Conflict — idempotency key reused with different parameters.
429Too many requests — back off and honour Retry-After.
5xxServer error — retry with the same idempotency key.
402 Request failedError object
{
  "error": {
    "type": "payment_error",
    "code": "insufficient_funds",
    "message": "The card has insufficient funds for this deposit.",
    "decline": "soft",
    "retryable": true,
    "payment": "pay_9Xc1Pd4ReN",
    "request_id": "req_2Hk7Tn5Vb3"
  }
}

Decline codes

CodeWhat happenedType
insufficient_fundsThe player's balance is too lowSoft · cascades
do_not_honorGeneric issuer declineSoft · cascades
authentication_requiredA 3-D Secure challenge is neededSoft · challenge
method_unavailableThe method is temporarily down in this countrySoft · fallback
risk_blockedBlocked by your Fraud shield rulesHard
limit_exceededA player or responsible-gaming limit was reachedHard

Reference

SDKs

Official libraries wrap authentication, retries, idempotency and webhook verification. They are versioned with the API and open to contributions.

Node.jsv4.12.0
npm install @orbita/node
Pythonv3.8.1
pip install orbita
PHPv2.9.4
composer require orbita/orbita-php
Gov2.6.0
go get orbitapay.dev/orbita-go/v2
Java / Kotlinv1.14.2
dev.orbitapay:orbita-java:1.14.2
Cashier SDKiOS · Android · Web

Drop-in cashier with native wallets, saved methods and 3-D Secure built in.

Was this page helpful?