ribbonPay

Getting access

ribbonPay is a managed fraud-review service. API keys, webhook signing secrets, and field contracts are provisioned by our team — there is no self-serve signup, and this is not a fraud guarantee.

ribbonPay Direct/API Integration Guide

This guide is the published Direct/API documentation (also served at /docs). The interactive OpenAPI reference is at /docs/api; the machine-readable spec is at /openapi.json. Credentials are provisioned by ribbonPay ops — there is no self-serve signup.

This guide is for merchants whose checkout or order-management system connects to ribbonPay over HTTPS — custom carts, Adobe Commerce (Magento), BigCommerce custom flows, headless storefronts, and any platform where your developers call our REST API directly.

Not for Shopify. Shopify merchants install the ribbonPay app; orders arrive via Shopify webhooks and decisions are written back to Shopify automatically. This guide covers the Direct/API path only (the same API the WooCommerce plugin uses under the hood).


1. Integration model

ribbonPay is a server-to-server integration. Your backend calls ribbonPay when an order is placed, holds fulfillment until ribbonPay approves it, and acts on the decision we return.

  1. Your backend POSTs the order to /api/v1/orders with a Bearer API key.
  2. ribbonPay returns 200 with decision PENDING, SHIP, or CANCEL.
  3. Hold capture and fulfillment until you receive SHIP.
  4. Optionally PATCH late gateway data (AVS, CVV, BIN).
  5. Analysts review PENDING orders.
  6. ribbonPay POSTs a signed webhook with the final SHIP or CANCEL.
  7. On SHIP, fulfill; on CANCEL, void or refund.

When to call ribbonPay

Call POST /api/v1/orders immediately after payment authorization succeeds and before you capture funds or ship goods. Your integration must:

  1. Authorize payment with your gateway (do not capture yet, unless your business model requires otherwise).
  2. Submit the order to ribbonPay and read the synchronous response.
  3. Hold fulfillment until you receive an explicit SHIP decision (synchronous response or later webhook).
  4. Act on the final decision:
    • SHIP — capture payment (if not already captured) and fulfill the order.
    • CANCEL — void authorization, refund, or cancel the order per your gateway workflow.
    • PENDING — keep the order on hold; a human analyst will review it. The final decision arrives via signed webhook (see §7).

Training period (new merchants)

During the initial onboarding period (~90 days), ribbonPay routes orders to human review by default, so the synchronous API response will be PENDING for most orders. Automatic decisions are allowed during training: as our analysts identify reliable signals for your store, they may introduce auto-approve or auto-cancel rules, so your integration must handle a synchronous SHIP or CANCEL from day one. You must also implement the webhook receiver — that is how you receive SHIP and CANCEL after analyst review.


2. What ribbonPay provides / what we need from you

ribbonPay provides (integration packet)

ItemDescription
API base URLProduction host for all requests (provided at onboarding), e.g. https://<your-ribbonpay-host>
API keySecret bearer token, format rp_live_ + 32 characters (40 characters total). Shown once at provisioning. Store server-side only.
Webhook signing secretPer-merchant secret used to verify decision callbacks (HMAC-SHA256). Provided at onboarding.
Field contractRequired and optional order fields (§4). We may configure decision_required_fields for your account — fields you must supply before scoring runs.
Support contactribbonPay integration/onboarding contact for credential and field-contract questions

We need from you

ItemDescription
Webhook receiver URLHTTPS endpoint on your infrastructure that accepts POST decision callbacks. Required for orders that go to analyst review.
Field availability matrixWhich payment, customer, and device fields your cart/gateway can supply at order creation vs. a few seconds later (for PATCH).
Fulfillment-hold confirmationWritten confirmation that you will not capture/ship until SHIP.
Test credentials / sandbox ordersAbility to place test orders in a staging environment before go-live (coordinate with ribbonPay).

3. Authentication

Every API request must include your API key in the Authorization header:

Authorization: Bearer rp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
RuleDetail
Key formatMust start with rp_live_ and be exactly 40 characters
StorageServer-side only — never embed in browser JavaScript, mobile apps, or public repos
ScopeOne API key identifies one merchant account; you can only read/update your own orders

Authentication errors (401)

reasonMeaning
missing_headerNo Authorization: Bearer … header
invalid_formatKey does not match rp_live_ + 32-char pattern
not_foundKey is revoked or unknown
inactiveMerchant account or key is inactive

All responses include an X-Request-Id header — include it when contacting ribbonPay support.


4. Submit an order — POST /api/v1/orders

POST /api/v1/orders

Creates (or idempotently returns) an order and runs enrichment, scoring, and rules. Returns a synchronous decision when data is complete.

Required fields

FieldTypeConstraints
external_order_idstringYour order ID. Idempotency key — safe to retry with the same value.
customer_emailstringValid email
billing_addressobjectSee address shape below
shipping_addressobjectSee address shape below
ip_addressstringShopper IP at checkout (not your server IP)
line_itemsarrayMin 1 item; see line item shape below
order_totalnumber≥ 0

Address shape (both billing and shipping):

KeyTypeConstraints
streetstringMin 1 character
citystringMin 1 character
statestringMin 1 character
zipstringMin 1 character
countrystringISO 3166-1 alpha-2 (e.g. "US") — uppercased on ingest

Line item shape:

KeyTypeConstraints
skustringMin 1 character
quantityinteger> 0
pricenumber≥ 0
descriptionstringOptional, max 500 characters

Send everything your gateway and cart can provide. More payment and customer context improves review quality.

FieldTypeConstraints / notes
customer_namestring
customer_phonestring
billing_namestring
billing_phonestring
order_subtotalnumber≥ 0
order_taxnumber≥ 0
order_shippingnumber≥ 0
currencystring3-letter ISO code (default USD)
order_placed_atstringISO 8601 timestamp
discount_totalnumber≥ 0
discount_codesstring[]
channelstringSales channel / source
gatewaystringPayment gateway name
payment_methodstringe.g. credit_card, paypal
ship_methodstringe.g. UPS Ground
order_notesstring
order_statusstringYour platform order status
payment_statusstringGateway payment status
avs_codestringAddress Verification Service code
cvv_codestringCVV/CVC result code
card_binstringExactly 6 digits
card_last4stringExactly 4 digits
card_brandstringe.g. visa, mastercard
card_exp_monthinteger1–12
card_exp_yearinteger2000–2100
auth_resultstringGateway authorization result
three_ds_resultstring3-D Secure outcome
cavv_resultstringCAVV / liability shift indicator
customer_created_atstringISO 8601 — customer account creation
customer_first_order_atstringISO 8601
customer_last_order_atstringISO 8601
customer_order_countinteger≥ 0
customer_total_spendnumber≥ 0
shipping_recipient_namestringIf different from buyer
shipping_recipient_emailstringValid email
shipping_recipient_phonestring
device_idstringDevice fingerprint ID if you collect one
device_session_idstringPer-checkout session id from the ribbonPay browser collector (max 64 chars); joins collector signals to this order
device_latnumber−90 to 90; must be sent with device_lng
device_lngnumber−180 to 180; must be sent with device_lat

Unknown fields are rejected (400 invalid_request). Send only fields listed above.

Minimal request example

{
  "external_order_id": "ORD-10042",
  "customer_email": "buyer@example.com",
  "billing_address": {
    "street": "1 Main St",
    "city": "Austin",
    "state": "TX",
    "zip": "78701",
    "country": "US"
  },
  "shipping_address": {
    "street": "1 Main St",
    "city": "Austin",
    "state": "TX",
    "zip": "78701",
    "country": "US"
  },
  "ip_address": "203.0.113.45",
  "line_items": [
    { "sku": "WIDGET-01", "quantity": 1, "price": 49.99 }
  ],
  "order_total": 49.99
}

Full request example (with payment data)

{
  "external_order_id": "ORD-10042",
  "customer_email": "buyer@example.com",
  "customer_name": "Jane Buyer",
  "customer_phone": "+15125550100",
  "billing_address": {
    "street": "1 Main St",
    "city": "Austin",
    "state": "TX",
    "zip": "78701",
    "country": "US"
  },
  "shipping_address": {
    "street": "99 Oak Ave",
    "city": "Dallas",
    "state": "TX",
    "zip": "75201",
    "country": "US"
  },
  "ip_address": "203.0.113.45",
  "line_items": [
    {
      "sku": "WIDGET-01",
      "quantity": 2,
      "price": 24.99,
      "description": "Premium widget"
    }
  ],
  "order_total": 54.98,
  "order_subtotal": 49.98,
  "order_tax": 5.00,
  "currency": "USD",
  "order_placed_at": "2026-06-29T15:30:00Z",
  "gateway": "authorize_net",
  "payment_method": "credit_card",
  "payment_status": "authorized",
  "avs_code": "Y",
  "cvv_code": "M",
  "card_bin": "411111",
  "card_last4": "1111",
  "card_brand": "visa",
  "card_exp_month": 12,
  "card_exp_year": 2028,
  "customer_order_count": 3,
  "customer_total_spend": 450.00,
  "ship_method": "UPS Ground"
}

Success response (200)

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "decision": "PENDING",
  "reason_code": "no_decision_rule",
  "timestamp": "2026-06-29T15:30:01.123Z"
}
FieldDescription
order_idribbonPay internal UUID — store for support correlation
decisionSHIP, CANCEL, or PENDING
reason_codeMachine-readable reason for the decision
timestampOrder creation time (ISO 8601)
awaiting_fieldsPresent when required fields are missing (see below)

Awaiting data (awaiting_fields)

If your merchant account has a decision_required_fields contract and the payload is missing those fields, the order is stored but not scored yet:

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "decision": "PENDING",
  "reason_code": "awaiting_data",
  "timestamp": "2026-06-29T15:30:01.123Z",
  "awaiting_fields": ["avs_code", "card_bin"]
}

Send the missing fields via PATCH /api/v1/orders/{external_order_id} (§5). When complete, ribbonPay runs enrichment and decision automatically.

curl example

curl -X POST "https://<your-ribbonpay-host>/api/v1/orders" \
  -H "Authorization: Bearer rp_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d @order.json

5. Backfill / update — PATCH /api/v1/orders/{external_order_id}

PATCH /api/v1/orders/{external_order_id}

Send only the fields you want to add or correct. Use this when gateway data (AVS, CVV, BIN) arrives after the initial order submission — the same pattern used by the WooCommerce + Authorize.net integration.

Rules

RuleDetail
Identityexternal_order_id is in the URL; customer_email cannot be changed after create
BodyAt least one updatable field required; unknown fields rejected
Same validatorscard_bin (6 digits), card_last4 (4 digits), address shape, etc.
device_lat / device_lngMust be sent together if either is sent

Updatable fields

All optional fields from §4 except external_order_id and customer_email (includes device_session_id for late collector correlation).

Common PATCH payloads:

{
  "avs_code": "Y",
  "cvv_code": "M",
  "card_bin": "411111",
  "card_last4": "1111",
  "card_brand": "visa",
  "payment_status": "authorized"
}

Response shapes (200)

The response includes updated_fields (list of field names applied) and varies by outcome:

Still awaiting required fields:

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "awaiting_data",
  "awaiting_fields": ["card_bin"],
  "updated_fields": ["avs_code", "cvv_code"]
}

Data merged, order not yet complete for decision (no contract transition):

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "decision": "PENDING",
  "reason_code": "awaiting_data",
  "risk_score": 0,
  "timestamp": "2026-06-29T15:30:05.000Z",
  "updated_fields": ["gateway"]
}

Completeness reached — decision run:

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "decision": "PENDING",
  "reason_code": "no_decision_rule",
  "risk_score": 42,
  "timestamp": "2026-06-29T15:30:05.000Z",
  "updated_fields": ["avs_code", "card_bin"]
}

Order already decided (SHIP or CANCEL) — fields merged, decision unchanged:

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "decision": "SHIP",
  "reason_code": "analyst_ship",
  "risk_score": 15,
  "timestamp": "2026-06-29T16:00:00.000Z",
  "updated_fields": ["ship_method"],
  "status": "merged_post_decision"
}

Payment error detected (via payment_status):

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "payment_error",
  "reason_code": "payment_error",
  "timestamp": "2026-06-29T15:30:05.000Z",
  "updated_fields": ["payment_status"]
}

Merchant cancelled (via order_status or payment_status):

{
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "merchant_cancelled",
  "reason_code": "merchant_cancelled",
  "timestamp": "2026-06-29T15:30:05.000Z",
  "updated_fields": ["order_status"]
}

Errors

StatusMeaning
404No order with that external_order_id for your merchant
400Validation error (empty body, bad field format, unknown fields)
401Authentication failure
429Rate limit exceeded
500Internal error — safe to retry PATCH for idempotent field updates

6. Decision handling

DecisionMeaningYour action
SHIPApprove for fulfillmentCapture payment (if held) and ship
CANCELDecline / do not fulfillVoid, refund, or cancel the order
PENDINGUnder reviewDo not ship. Wait for webhook with final decision

Where decisions arrive

PathWhen
SynchronousPOST /api/v1/orders responseImmediate, when data is complete and rules auto-decide (less common during the training period, but possible once auto-decision rules are introduced)
SynchronousPATCH responseWhen a previously incomplete order becomes complete and rules auto-decide
Asynchronous — signed webhook (§7)After analyst review, or any SHIP / CANCEL that was not returned synchronously

Webhooks are sent only for SHIP and CANCEL — never for PENDING.

If the synchronous response is PENDING, you must implement the webhook receiver to get the final outcome.

Common reason_code values

reason_codeTypical meaning
no_decision_ruleNo auto-decision rule matched; order queued for analyst review (normal during onboarding)
awaiting_dataRequired fields missing; send PATCH when data is available
payment_errorGateway reported a hard payment failure
merchant_cancelledOrder was cancelled/refunded/voided on your side
rule_matchAn automated rule decided the order
analyst_ship / analyst_cancelHuman analyst approved or declined
enrichment_failure_pendingExternal enrichment unavailable; queued for review

7. Receiving decisions (webhook)

ribbonPay POSTs to the webhook_url configured on your merchant account when an order receives a final SHIP or CANCEL decision.

Request from ribbonPay

POST https://your-site.com/ribbonpay/webhook
Content-Type: application/json
X-Ribbonpay-Event: order.decision
X-Ribbonpay-Signature: <hex-encoded HMAC-SHA256>
X-Ribbonpay-Signature-Previous: <hex>   # only during the 7-day window after secret rotation
X-Ribbonpay-Delivery-Id: <uuid>   # present on deliveries created after webhook_deliveries rollout

Body:

{
  "event": "order.decision",
  "event_id": "a1b2c3d4e5f6789012345678abcdef01",
  "order_id": "550e8400-e29b-41d4-a716-446655440000",
  "external_order_id": "ORD-10042",
  "decision": "SHIP",
  "reason_code": "analyst_ship",
  "timestamp": "2026-06-29T16:45:00.000Z"
}
FieldDescription
eventAlways order.decision
event_idStable dedup key for this decision event (32-char hex). Same across QStash redeliveries and ops manual retries of the same decision; changes if the order is decided again with a new decided_at.
order_idribbonPay internal UUID
external_order_idYour order ID — use this to match your order record
decisionSHIP or CANCEL
reason_codeMachine-readable reason
timestampWhen the decision was recorded (ISO 8601)

At-least-once delivery: queue delivery can deliver the same event more than once. Deduplicate on event_id (preferred) before applying the decision. The optional X-Ribbonpay-Delivery-Id header identifies a specific QStash delivery attempt/message for tracing — do not use it as the business dedup key.

Signature verification

  1. Read the raw request body as a string (before JSON parsing).
  2. Compute HMAC-SHA256 of that raw body using your webhook signing secret.
  3. Compare the result (hex-encoded, lowercase) to the X-Ribbonpay-Signature header using a constant-time comparison.
  4. During secret rotation, also accept a match against X-Ribbonpay-Signature-Previous (present for 7 days after ribbonPay rotates your signing secret). Accept the request if either signature verifies.
  5. Reject the request if neither signature matches.

The request body is sent as canonical JSON (object keys sorted alphabetically at every nesting level). Verify against the exact bytes received — do not re-serialize parsed JSON unless your serializer produces identical output.

Node.js example

import { createHmac, timingSafeEqual } from 'crypto'

function verifyRibbonpayWebhook(rawBody, signatureHeader, secret) {
  const expected = createHmac('sha256', secret)
    .update(rawBody, 'utf8')
    .digest('hex')

  const received = signatureHeader.trim()
  if (expected.length !== received.length) return false

  return timingSafeEqual(
    Buffer.from(expected, 'hex'),
    Buffer.from(received, 'hex')
  )
}

// Express: use express.raw({ type: 'application/json' }) or req.rawBody
// Then:
// if (!verifyRibbonpayWebhook(rawBody, req.headers['x-ribbonpay-signature'], WEBHOOK_SECRET)) {
//   return res.status(401).send('Invalid signature')
// }

PHP example (Magento / WooCommerce-style backends)

<?php
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_RIBBONPAY_SIGNATURE'] ?? '';
$secret = getenv('RIBBONPAY_WEBHOOK_SECRET');

$expected = hash_hmac('sha256', $rawBody, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$payload = json_decode($rawBody, true);
$externalOrderId = $payload['external_order_id'];
$decision = $payload['decision']; // SHIP or CANCEL

Your webhook handler must

RequirementDetail
Respond 2xx quicklyAcknowledge receipt; do heavy work asynchronously if needed
Be idempotentribbonPay retries on network errors and 5xx responses — the same decision may be delivered more than once
Use external_order_idPrimary key to locate your order
Verify signature before actingNever fulfill or cancel based on an unverified payload

Retry behavior

Your responseribbonPay behavior
2xx or 4xxDelivery considered complete (fix 4xx bugs on your side)
5xx or network timeoutRetried automatically

8. Edge cases and status reference

Idempotency

external_order_id is unique per merchant. Submitting the same ID twice returns the original order and decision (200) — no duplicate row is created. Safe to retry on network failures.

Payment error (payment_error)

If payment_status is one of declined, failed, error, or refused (case-insensitive), the order is recorded with status payment_error and is not scored for fraud review. No fulfillment action is expected from ribbonPay.

Merchant cancelled (merchant_cancelled)

If payment_status or order_status is cancelled, refunded, or voided (case-insensitive), the order is recorded as merchant_cancelled — the shopper or merchant cancelled before ribbonPay could decide.

Rate limiting (429)

Default limit: 60 requests per minute per merchant (configurable). Response includes:

{ "error": "rate_limited", "retry_after_seconds": 12 }

Header: Retry-After (seconds). Back off and retry.

Validation errors (400)

{
  "error": "invalid_request",
  "details": [ /* Zod issue objects */ ]
}

Common causes: missing required field, invalid email, country not 2 letters, card_bin not 6 digits, device_lat without device_lng, empty PATCH body, unknown JSON keys.

Error summary

HTTPerrorAction
400invalid_requestFix payload
401unauthorizedCheck API key
404not_foundPATCH target order does not exist
429rate_limitedRetry after Retry-After
500internal_errorRetry POST (idempotent) or contact support with X-Request-Id

9. Testing checklist

Use Postman, curl, or your HTTP client against your ribbonPay environment. Confirm each scenario and verify the order appears in the ribbonPay ops console.

Prerequisites

  • Merchant account provisioned with API key and webhook signing secret
  • webhook_url pointed at a test receiver (webhook.site, RequestBin, or local tunnel)
  • Ops console access to resolve PENDING orders (for webhook end-to-end test)

POST /api/v1/orders

#ScenarioExpected
1Minimal valid payload200, decision (typically PENDING during training)
2Full payload with AVS/CVV/BIN/card fields200, order stored with payment data
3Missing required field (e.g. ip_address)400 invalid_request
4Invalid card_bin (not 6 digits)400 invalid_request
5device_lat without device_lng400 invalid_request
6Missing fields in your decision_required_fields contract200, awaiting_fields array present
7"payment_status": "declined"200, decision: PENDING, reason_code: payment_error
8"order_status": "cancelled"200, decision: PENDING, reason_code: merchant_cancelled
9Same external_order_id submitted twice200, same order_id, no duplicate
10Missing / invalid API key401 unauthorized
11Malformed JSON body400 invalid_request

PATCH /api/v1/orders/{external_order_id}

#ScenarioExpected
12PATCH AVS/CVV/BIN onto order from #6200, updated_fields; may trigger decision when complete
13PATCH unknown field400 invalid_request
14PATCH nonexistent external_order_id404 not_found
15PATCH after order decided SHIP/CANCEL200, status: merged_post_decision, decision unchanged

Webhook receiver

#ScenarioExpected
16Resolve a PENDING order as SHIP in ops consoleWebhook POST received with decision: SHIP
17Verify X-Ribbonpay-Signature with your signing secretSignature validates against raw body
18Return 200 from your handlerDelivery logged as successful
19Resolve order as CANCELWebhook with decision: CANCEL; your system cancels/voids

End-to-end flow

#ScenarioExpected
20POST order → hold fulfillment → receive SHIP webhook → capture/shipFull happy path
21POST order → receive CANCEL webhook → void/refundFull decline path
22POST incomplete → PATCH gateway data → decision runsTwo-step intake path

9. Device collection (browser collector)

ribbonPay ships a hosted browser collector for Direct/API merchants and the WooCommerce plugin. It follows a Kount DDC-style pattern: the shopper's browser posts device signals keyed by a per-checkout session_id; your order POST/PATCH carries the same value as device_session_id; ribbonPay joins them server-side and derives a stable device_id fingerprint.

Shopify checkout uses a separate no-code Custom Pixel that feeds the same ingest endpoint — see shopify-device-collection-setup.md (ops-installed; not something the merchant integrates via this guide).

Site key

Ops provisions a publishable site key (rp_site_ + random suffix). This is not your secret rp_live_… API key. Never embed the live API key in storefront HTML.

Checkout embed

Generate a fresh session_id per checkout (UUID recommended). Set it in a first-party cookie if useful for your plugin, and pass the same value as device_session_id on POST /api/v1/orders.

<script
  src="https://YOUR_RIBBONPAY_HOST/device/v1/collector.js"
  data-rp-site-key="rp_site_xxxxxxxxxxxxxxxxxxxxxxxx"
  data-rp-session="YOUR_CHECKOUT_SESSION_ID"
  data-rp-ingest="https://YOUR_RIBBONPAY_HOST/api/device/v1/collect"
  async
></script>

Alternative config object (if you load the script programmatically):

window.ribbonpayDevice = {
  siteKey: 'rp_site_…',
  sessionId: 'YOUR_CHECKOUT_SESSION_ID',
  ingestUrl: 'https://YOUR_RIBBONPAY_HOST/api/device/v1/collect',
}

Ingest contract

ItemDetail
EndpointPOST /api/device/v1/collect
Authsite_key in JSON body (publishable key)
CORSOpen (Access-Control-Allow-Origin: *); no cookies/credentials
Body{ "site_key", "session_id", "client_token?", "signals" }
Order joinSame session_id as device_session_id on the order API

Collection may arrive before or after the order POST; both orderings are supported. If signals arrive late, ribbonPay backfills device enrichment on pending review orders.

Order field

{
  "external_order_id": "ORD-10042",
  "device_session_id": "YOUR_CHECKOUT_SESSION_ID",
  "...": "..."
}

ribbonPay derives device_id from collected signals. Merchants may still send their own device_id; merchant-supplied values take precedence.


10. Known limitations

LimitationDetail
Shopify device collectionBrowser collector + device_session_id apply to Direct/API and WooCommerce plugin paths only. Shopify needs a separate web-pixel integration (TBD).
No pull from your cartUnlike Shopify (where ribbonPay pulls payment data via Admin API), Direct/API merchants push all data. If a field is not in your POST or PATCH, ribbonPay cannot retrieve it from your platform.
Training periodExpect synchronous PENDING on most orders; auto-approve/auto-cancel rules may be introduced during training, so handle synchronous SHIP/CANCEL too. Webhook implementation is mandatory before go-live.

Quick reference

OperationMethodPath
Submit orderPOST/api/v1/orders
Update / backfillPATCH/api/v1/orders/{external_order_id}
Device collector JSGET/device/v1/collector.js
Device signal ingestPOST/api/device/v1/collect
Health checkGET/api/health

Auth: Authorization: Bearer rp_live_…

Decision webhook headers: X-Ribbonpay-Signature, optional X-Ribbonpay-Signature-Previous (rotation grace), X-Ribbonpay-Event: order.decision, optional X-Ribbonpay-Delivery-Id

Support: Include X-Request-Id from any API response when contacting ribbonPay.

Back to top