Browse documentation
Part 1
Merchant Manual
A tour of every feature in the platform — what real-world problem it solves for your business, and exactly how to use it.
Platform overview
The problem it solves
Payment infrastructure is fragmented — cards, bank rails and crypto each live in a different portal, each with their own KYC, onboarding and reconciliation headache.
How it works
PayOrchestrate gives you one account that unifies two providers: Swipe (cards, SEPA, SWIFT, ACH, card-linked payouts) and B2BinPay (crypto deposits). You configure them once, and every payment link, embed frame, transaction and payout flows through the same dashboard.
Each merchant account has: a Swipe customer + primary wallet, an optional B2BinPay wallet, an embed key for your website, and a full audit trail of transactions.
Getting paid — prerequisites
The problem it solves
You need a legally compliant route to receive customer money. Different rails (card vs. SEPA vs. crypto) have different compliance and onboarding requirements.
How it works
Enable at least one provider before you can accept a single payment. Swipe covers fiat (card/bank); B2BinPay covers crypto. You can enable both.
- Swipe — Click Enable in the Swipe router. Complete KYC to unlock bank rails (SEPA/SWIFT/ACH). Card rails work immediately after enable.
- B2BinPay — Create a wallet in B2BinPay Back Office, copy the Wallet ID into our Source Configuration, click Save.
Swipe — cards, bank rails & payouts
The problem it solves
Accepting card payments or bank transfers normally means a merchant account, a gateway, a processor, compliance onboarding and weeks of back-and-forth.
How it works
Swipe abstracts all of that behind a single wallet. You enable it in one click, pass KYC once, and you get card pay-ins, virtual IBANs for SEPA/SWIFT/ACH, and outbound payouts from the same balance.
1. Enable Swipe. Swipe sidebar → Credentials → Enable Swipe. We create a customer + wallet; you’ll see the IDs once provisioned.
2. Pass KYC. Business Identity → Start KYC. Required for bank rails; cards work pre-KYC.
3. Create a pay-in. Simulation Center → Pay-in Execution. Enter amount/currency, choose Card, Quote, Execute — you get a hosted checkout URL to send the customer.
4. Provision a virtual bank account. Virtual Route → pick type (SEPA Node, SWIFT, ACH), country, currency → Provision Route. You get an IBAN/account number.
5. Send a payout. Global Payout Settle → destination + amount → Quote → Settle.
B2BinPay — crypto deposits
The problem it solves
Accepting crypto means managing wallets, monitoring chains for confirmations, converting to fiat, and reconciling to customer orders.
How it works
We connect to your B2BinPay wallet and generate deposit links on demand. Customers pay to a hosted page; B2BinPay credits your wallet; we surface the status back to you via webhook.
1. Link wallet. B2BinPay sidebar → Source Configuration → paste Wallet ID from B2BinPay Back Office → Save. Green dot + “Wallet Linked” confirms it.
2. Create deposit link. Deposit Execution → Create Deposit Link. We return the hosted payment URL. Copy the link or use Copy embed iframe to drop it straight on your site.
Payment Router
The problem it solves
Different orders need different rails — a small card payment vs. a €50k SEPA vs. a crypto deposit. Juggling three UIs is slow and error-prone.
How it works
The Router is a single switchboard: pick the provider, fill in the order details, generate a link or execute a payout. It wraps both Swipe and B2BinPay so operational workflows stay in one place.
Use Router → Simulation Center to test pay-ins and payouts without writing code.
Transactions & reconciliation
The problem it solves
Finance teams waste hours stitching provider CSVs to internal orders. Disputes and refunds are especially painful without a single source of truth.
How it works
Every pay-in, payout, deposit and settlement across Swipe and B2BinPay is stored against your account. The Transactions view is your canonical ledger — filterable by status, rail, provider, date.
Open it from Router → Transactions.
Profile & credentials
The problem it solves
Credentials sprawl (API keys, wallet IDs, 2FA seeds) is the #1 source of breached merchant accounts. Most platforms leave you to manage this on your own.
How it works
Profile centralises your identity, 2FA status, publishable key, Swipe customer/wallet IDs, embed key and credential vaults. Secrets are masked by default; 2FA via Google Authenticator is required on every sign-in.
Your publishable key (safe to use on your site) and embed key (scopes the iframe to your account) live here. Service-role keys never appear client-side.
Part 2
API Integration Manual
Connect your website or application to PayOrchestrate. Today the primary integration surface is the embed checkout iframe, backed by server-to-server webhooks for status events.
Integration overview
- Merchant enables Swipe and/or links B2BinPay — account is provisioned.
- Merchant copies their embed key from Profile or from the provider page in the Router.
- Merchant drops an
iframeinto their checkout page, passing amount + currency. - Customer pays in the frame; funds land in the merchant’s Swipe wallet or B2BinPay wallet.
- Our server fires a webhook to the merchant’s configured callback URL with the final status.
Your embed key
The embed key identifies which merchant account a payment belongs to. Find it in:
- Profile → System Integration → Embed Key
- Router → Swipe → Credentials
- Router → B2BinPay → Embed checkout iframe
Treat the embed key like a public key — safe to put in HTML, but it scopes all payments to your account. Rotate it only if you suspect abuse.
Embed checkout URL
https://payorchestrate.com/embed/checkout?key=YOUR_EMBED_KEY&amount=99.50¤cy=EUR
Load this URL inside an iframe on your site. We resolve the merchant from key, create a fresh payment for amount + currency, and render the provider’s checkout inside the frame.
Drop-in iframe
<iframe src="https://payorchestrate.com/embed/checkout?key=YOUR_EMBED_KEY&amount=99.50¤cy=EUR" title="Pay" width="100%" height="500" style="border:0; max-width: 480px;" ></iframe>
The frame is self-contained — it handles card entry, 3-D Secure, wallet selection and crypto QR codes depending on the provider and rail.
URL parameters
| Param | Required | Description |
|---|---|---|
| key | Yes | Your merchant embed key. |
| amount | Yes* | Decimal amount (e.g. 99.50). Not required if link is used. |
| currency | Yes* | ISO 4217 code (EUR, USD, GBP) or crypto ticker for B2BinPay flows. |
| provider | No | swipe (default) or b2binpay. |
| link | No | URL-encoded existing hosted payment link. When set, we render that link instead of creating a new payment. |
| reference | No | Your internal order ID. Echoed back on the webhook. |
Embedding an existing link
If you created a payment link in the Router (Swipe Pay-in Execution or B2BinPay Deposit Link), embed it directly — no new payment is created:
https://payorchestrate.com/embed/checkout?key=YOUR_EMBED_KEY&link=https%3A%2F%2F...
Webhooks & callbacks
When a payment’s status changes (authorised, captured, failed, refunded, deposit confirmed), we POST a JSON payload to your callback URL. Status events originate from the provider and are relayed through our servers at:
POST https://payorchestrate.com/api/webhooks/swipelux POST https://payorchestrate.com/api/webhooks/b2binpay
Representative payload:
{
"event": "payment.succeeded",
"provider": "swipe",
"merchant_account_id": "acc_...",
"payment_id": "pay_...",
"reference": "ORDER-12345",
"amount": "99.50",
"currency": "EUR",
"status": "succeeded",
"created_at": "2026-04-15T10:22:31Z"
}Your endpoint must respond with HTTP 2xx within 10 seconds. Non-2xx responses are retried with exponential backoff for up to 24 hours. Always verify the signature header (X-PayOrchestrate-Signature) before trusting the payload.
Your outbound webhooks
In addition to PSP callbacks hitting our platform, you can register your own HTTPS endpoint to receive normalized payment events for your merchant account. Configure this under Integrations → Webhooks.
- Events fire when payments are created via the REST API, when PSP status webhooks update the ledger, and when you refund.
- Each delivery is signed with HMAC-SHA256 (
X-Webhook-Signature). - Choose event patterns such as
payment.*orpayment.completed.
{
"id": "evt_abc123",
"type": "payment.completed",
"created_at": "2026-06-01T12:00:00.000Z",
"livemode": true,
"data": {
"transaction": {
"id": "uuid",
"reference": "ORDER-12345",
"provider": "cyberpay",
"status": "completed",
"amount": 100,
"currency": "USD"
}
}
}Testing & go-live
- Use Simulation Center in the Router to generate test pay-ins/payouts end-to-end without real funds.
- Load your embed URL in a local HTML file and confirm the frame renders and posts back to your webhook.
- Before going live: verify 2FA is enabled on your profile, KYC is approved for bank rails, and your production webhook endpoint responds 2xx to a simulated event.
Part 3
REST API (v1)
A server-to-server JSON API for creating checkout sessions programmatically. Ideal when you need to generate a redirect URL from your backend before sending the customer to a hosted payment page.
Overview & authentication
All /api/v1/* endpoints are authenticated with a secret API key passed as a Bearer token. Keys are scoped to your merchant account and can be created and revoked from Integrations → API Keys.
Key security rules
- Keys start with
sk_live_ - Shown once at creation — copy immediately
- Never expose in client-side code or public repos
- Revoke instantly from the dashboard if compromised
Base URL
https://payorchestrate.com/api/v1
Auth header
Authorization: Bearer sk_live_<your-key>
Discovery — GET /api/v1
curl https://payorchestrate.com/api/v1
Returns the full endpoint catalog, auth rules, and supported providers. No API key required.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1 | Discovery (no auth) |
| POST | /api/v1/checkout | Create pay-in session (cyberpay) |
| GET | /api/v1/transactions | List payments |
| GET | /api/v1/transactions/{id} | Get status (+ optional refresh) |
| POST | /api/v1/refunds | Refund a pay-in |
| POST | /api/v1/payouts | Create or execute payout |
GET /api/v1 — API discovery
Call this endpoint during integration to discover available routes programmatically. The response includes authentication instructions and the same endpoint list documented here.
curl https://payorchestrate.com/api/v1
POST /api/v1/checkout
Creates a hosted checkout session for the specified provider and returns a checkout_url to redirect your customer to.
Method
POSTContent-Type
application/jsonAuth
Bearer sk_live_…POST https://payorchestrate.com/api/v1/checkout
Authorization: Bearer sk_live_YOUR_KEY
Content-Type: application/json
{
"provider": "cyberpay",
"amount": 100.00,
"currency": "USD",
"country": "US",
"redirect_url": "https://yoursite.com/thank-you",
"reference": "ORDER-12345",
"customer": {
"email": "user@example.com",
"phone": "+1234567890",
"first_name": "John",
"last_name": "Doe"
}
}Request body reference
| Field | Type | Required | Description |
|---|---|---|---|
| provider | string | Yes | Payment provider. Currently: cyberpay |
| amount | number | Yes | Positive decimal (e.g. 100.00) |
| currency | string | Yes | ISO 4217 code — USD, EUR, GBP, etc. |
| country | string | No | ISO 3166-1 alpha-2 (e.g. US). Defaults to currency’s home country. |
| redirect_url | string | No | Where to send the customer after payment. Defaults to your platform home page. |
| reference | string | No | Your internal order ID. Echoed back on webhooks. Auto-generated if omitted. |
| customer object | |||
| customer.email | string | Yes | Customer email address. |
| customer.phone | string | Yes | Customer phone in E.164 format (e.g. +12125551234). |
| customer.first_name | string | No | Defaults to "Customer". |
| customer.last_name | string | No | Defaults to "User". |
GET /api/v1/transactions
List ledger rows for your merchant account. Results are ordered newest first. Use filters to reconcile by status, provider, or your merchant reference.
GET https://payorchestrate.com/api/v1/transactions?limit=50&status=pending&provider=cyberpay Authorization: Bearer sk_live_YOUR_KEY
| Query param | Description |
|---|---|
| limit | 1–100, default 50 |
| status | pending, completed, failed, refunded, etc. |
| provider | cyberpay, payagency, swipe, b2binpay |
| direction | payin, payout, adjustment |
| reference | Match external_id or internal UUID |
| created_after | ISO 8601 lower bound |
| created_before | ISO 8601 upper bound |
| include=raw | Include PSP raw_response on each row |
{
"ok": true,
"count": 2,
"transactions": [
{
"id": "uuid",
"reference": "ORDER-12345",
"provider": "cyberpay",
"direction": "payin",
"status": "completed",
"amount": 100,
"currency": "USD",
"checkout_url": "https://cashier.cyberpay.link/...",
"created_at": "2026-06-01T12:00:00.000Z"
}
]
}GET /api/v1/transactions/{id}
Fetch a single transaction by internal id (UUID) or your merchant reference (stored as external_id).
GET https://payorchestrate.com/api/v1/transactions/ORDER-12345?refresh=true Authorization: Bearer sk_live_YOUR_KEY
refresh=true— polls Cyberpay or PayAgency for the latest status and updates your ledger.include=raw— includes the PSP raw payload on the transaction object.
{
"ok": true,
"refreshed": true,
"provider_status": "COMPLETED",
"transaction": {
"id": "uuid",
"reference": "ORDER-12345",
"status": "completed",
"provider": "cyberpay"
}
}POST /api/v1/refunds
Refund a completed pay-in. The original transaction must belong to your account and match the provider. Refunds cannot be undone.
POST https://payorchestrate.com/api/v1/refunds
Authorization: Bearer sk_live_YOUR_KEY
Content-Type: application/json
{
"provider": "cyberpay",
"reference": "ORDER-12345",
"reason": "Customer requested refund"
}Supported providers: cyberpay (uses merchant reference), payagency (uses PSP transaction id when available).
POST /api/v1/payouts
Initiate a payout. Behaviour depends on the provider:
- Cyberpay — returns a hosted
payout_url(cashier) for the beneficiary to complete. - PayAgency — direct card payout; requires
payout_details(wallet_id, card_number, expiry). - Swipe — two-step: first call creates a
quote_id; second call passesquote_idto execute.
// Cyberpay hosted payout
POST https://payorchestrate.com/api/v1/payouts
{
"provider": "cyberpay",
"amount": 50,
"currency": "USD",
"country": "US",
"customer": { "email": "payee@example.com", "phone": "+12125551234" }
}
// Swipe — step 1: create quote
{ "provider": "swipe", "amount": 50, "currency": "USD",
"destination_id": "swipe-beneficiary-id",
"customer": { "email": "payee@example.com", "phone": "+12125551234" } }
// Swipe — step 2: execute
{ "provider": "swipe", "quote_id": "quote_abc123",
"customer": { "email": "payee@example.com", "phone": "+12125551234" } }Response & errors
200 — Success
{
"ok": true,
"checkout_url": "https://cashier.cyberpay.link/session/...",
"reference": "ORDER-12345",
"provider": "cyberpay",
"amount": 100,
"currency": "USD"
}Redirect your customer to checkout_url. The session is typically valid for 15–30 minutes depending on the provider.
Error shape
{
"ok": false,
"error": "Human-readable message",
"code": "ERROR_CODE"
}| HTTP | code | Meaning |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid API key. |
| 400 | BAD_REQUEST | Request body is not valid JSON. |
| 400 | VALIDATION | A required field is missing or invalid. |
| 403 | PSP_UNAVAILABLE | Your account is not entitled to this provider. |
| 404 | NOT_FOUND | Transaction or quote not found. |
| 502 | PSP_ERROR | The provider rejected the request. See error for details. |
| 503 | PSP_UNAVAILABLE | Provider is disabled platform-wide. |
| 500 | INTERNAL | Unexpected server error. |
Outbound webhooks (to your server)
The REST API and PSP flows automatically trigger outbound webhooks when you configure a URL in Integrations → Webhooks. You do not call a separate API to enable this — save your endpoint once and events flow when the ledger changes.
Verify signatures on every request. Header format: X-Webhook-Signature: t=1690000000,v1=<hmac_hex> where v1 = HMAC-SHA256(secret, "{timestamp}.{body}").
Use Send test event in the dashboard to validate your handler before going live.
Inbound PSP webhooks & reconciliation
Pay-ins and payouts created via the API use the same webhook endpoints as the dashboard and embed flows. Configure your PSP dashboard to send notifications to:
- https://payorchestrate.com/api/webhooks/cyberpay
- https://payorchestrate.com/api/webhooks/payagency
- https://payorchestrate.com/api/webhooks/swipelux
- https://payorchestrate.com/api/webhooks/b2binpay
Use GET /api/v1/transactions/{reference}?refresh=true when you need an on-demand status poll before the webhook arrives. Your reference from checkout is stored as external_id and echoed in webhook payloads where the PSP supports it.
Code examples
cURL
curl -X POST https://payorchestrate.com/api/v1/checkout \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d ‘{
"provider": "cyberpay",
"amount": 100.00,
"currency": "USD",
"country": "US",
"redirect_url": "https://yoursite.com/thank-you",
"reference": "ORDER-12345",
"customer": {
"email": "user@example.com",
"phone": "+12125551234",
"first_name": "Jane",
"last_name": "Smith"
}
}’JavaScript (fetch)
const res = await fetch("https://payorchestrate.com/api/v1/checkout", {
method: "POST",
headers: {
"Authorization": "Bearer sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
provider: "cyberpay",
amount: 100.00,
currency: "USD",
country: "US",
redirect_url: "https://yoursite.com/thank-you",
reference: "ORDER-12345",
customer: {
email: "user@example.com",
phone: "+12125551234",
first_name: "Jane",
last_name: "Smith",
},
}),
});
const { ok, checkout_url, error } = await res.json();
if (!ok) throw new Error(error);
// Redirect the customer
window.location.href = checkout_url;Python (requests)
import requests
response = requests.post(
"https://payorchestrate.com/api/v1/checkout",
headers={
"Authorization": "Bearer sk_live_YOUR_KEY",
"Content-Type": "application/json",
},
json={
"provider": "cyberpay",
"amount": 100.00,
"currency": "USD",
"country": "US",
"redirect_url": "https://yoursite.com/thank-you",
"reference": "ORDER-12345",
"customer": {
"email": "user@example.com",
"phone": "+12125551234",
"first_name": "Jane",
"last_name": "Smith",
},
},
)
data = response.json()
if not data["ok"]:
raise Exception(data["error"])
checkout_url = data["checkout_url"]
# Redirect the customer to checkout_urlNeed something that isn’t covered?
Open a support ticket from the Router, or reach out to your account manager. We publish this manual alongside the product — if a feature changes, the docs do too.