For the complete documentation index, see llms.txt. This page is also available as Markdown.

Orders API Full Integration Merchant Guide

This guide is for merchants who integrate their own backend directly with ChargebackStop using COMPLETE orders on a CUSTOM_ORDERS integration. It is designed for larger merchants with one organisation, multiple MIDs, and the full prevention suite enabled.

Use this guide when:

  • You process payments through your own acquiring setup (one or more MIDs), rather than a processor ChargebackStop connects to directly.

  • You want to power Ethoca Alerts, Verifi RDR, Visa Order Insight, Mastercard Consumer Clarity, Compelling Evidence 3.0 (CE3.0) and First-Party Trust (FPT) from a single order feed.

  • You have (or will have) a live mode organisation and a test mode organisation.

If you already have a payment processor integration with ChargebackStop (Stripe, Adyen, etc.) and only need to enrich those transactions, use the Orders API partial enrichment merchant guide instead.

What you will build

Component
What it does
ChargebackStop surface

Order feed

Sends every order (with transactions, items, deliveries, customer and device data) shortly after payment

POST /v1/orders/

Lifecycle updates

Keeps orders current with refunds, disputes, delivery status and subscription changes

PATCH /v1/orders/{order_id}

Webhook consumer

Receives alert, enrolment and lookup events

Your HTTPS endpoint, configured in the dashboard

Alert resolution workflow

Refunds with your processor and resolves actionable alerts before the deadline

PATCH /v1/alerts/{alert_id}

Deflection monitoring

Tracks digital receipt lookups and CE3.0 deflection outcomes

lookup.* webhooks, GET /v1/lookups/

One order feed powers every tool:

Tool
Network
What it does
How your order data is used

Ethoca Alerts

Mastercard (+ Visa via Ethoca)

Early dispute/fraud alerts you resolve by refunding

Transaction identifiers (ARN, auth code, BIN, last 4, amount) match alerts to your orders

Verifi RDR

Visa

Eligible disputes are automatically accepted and refunded at network level

Refund and dispute records reconcile RDR outcomes; rulesets control which cases refund

Consumer Clarity

Mastercard

Shows cardholders a rich digital receipt in their banking app

Order details, items, deliveries, refunds and merchant profile build the receipt

Order Insight

Visa

Shows cardholders purchase details at the point of dispute

Order details, items, delivery and payment information build the response

CE3.0

Visa

Deflects disputes using the cardholder's history of legitimate purchases

customer_email plus device identifiers link purchases into qualifying history

First-Party Trust

Mastercard

Identifies legitimate transactions to reduce first-party fraud

customer_email, order_email and device identifiers

How your account is structured

Concept
ID prefix
Meaning in this integration

Organisation

org_

Your company. You have one live organisation and one test organisation.

Merchant

mrch_

One merchant per MID/CAID. An organisation with three MIDs has three merchants.

Integration

int_

Your CUSTOM_ORDERS order feed, linked to one or more merchants.

Enrolment

enrl_

A connection to one prevention programme (Ethoca Alerts, Verifi RDR, Consumer Clarity, Order Insight) for specific merchants.

Order

ord_

A record you create via the Orders API.

Alert

netalrt_

A network alert routed to your organisation via an enrolment.

Lookup

lkup_

A digital receipt or evidence request served from your order data.

Multiple MIDs

Each MID (or CAID) is represented by one merchant. Programmes are enrolled per MID:

  • Ethoca Alerts — enrolled by billing descriptor. Each MID's descriptors are registered on its enrolment.

  • Verifi RDR — enrolled by Visa BIN + CAID (or ARNs). One enrolment per BIN/CAID pair.

  • Consumer Clarity / First-Party Trust — enrolled per Mastercard merchant identity.

  • Order Insight / CE3.0 — enrolled by Visa BIN + CAID.

We recommend a single CUSTOM_ORDERS integration linked to all of your merchants. Alerts and lookups are matched against orders from integrations whose merchants overlap the enrolment's merchants, so one integration spanning every MID keeps the feed simple and matching complete.

What ChargebackStop sets up, and what you build

During onboarding the ChargebackStop team provisions for you:

  • Your live and test organisations.

  • One merchant per MID, in each organisation.

  • Your CUSTOM_ORDERS integration(s), linked to your merchants, with the validation rules for your enabled tools.

  • Enrolments for every programme: Ethoca Alerts (descriptors per MID), Verifi RDR (BIN + CAID per MID), Consumer Clarity (with First-Party Trust enabled) and Order Insight (with CE3.0 enabled).

You build:

  • API keys (created in your dashboard) and the order feed.

  • A webhook endpoint per environment.

  • The alert resolution workflow (refund with your processor, then resolve the alert).

  • Lifecycle updates (refunds, disputes, deliveries, subscriptions) into the Orders API.

Enrolment management endpoints (/v2/enrolments) and the Merchants API are partner-level APIs. Organisation-level API keys cannot call them — your enrolments and merchants are managed for you. Track enrolment progress via enrolment.created / enrolment.updated webhooks or in your dashboard, and treat a programme as live only when its enrolment status is ENABLED.

Environments

Both environments use the same base URL: https://api.chargebackstop.com.

Test
Live

Organisation

[TEST]-prefixed test mode organisation

Live mode organisation

API key

Created in the test organisation's dashboard

Created in the live organisation's dashboard

Alerts and lookups

Generated with the Simulations API

Real network traffic

Webhooks

Test endpoint configured on the test organisation

Production endpoint configured on the live organisation

Authentication

Create an API key in your dashboard under Settings → API keys, once per organisation (one test key, one live key). The key is displayed once — store it in your secrets manager immediately.

Every request uses the standard bearer scheme:

Organisation API keys created in the dashboard include the abilities this guide uses:

  • orders:read, orders:write, orders:update

  • alerts:read, alerts:write

  • lookups:read

  • integrations:read, integrations:write

  • rulesets:read, rulesets:write

  • simulations:alerts, simulations:enrollments, simulations:lookups, simulations:scheme_notices

Rate limits: 100 requests per minute per endpoint, per organisation. Each endpoint has an independent pool, and the limit applies to your organisation, not to the API key — creating extra keys does not raise it. A 429 response returns the code RATE_LIMITED with no Retry-After header, so use exponential backoff with jitter.

Step 1 — confirm your setup

Fetch your integration ID (you will send it with every order):

Find the integration with "type": "CUSTOM_ORDERS" in the response and store its id. Your organisation ID is shown in your dashboard and returned on every API object.

Store these IDs in your system's configuration:

Your system
ChargebackStop ID
Used for

Environment config

organisation_id

Every order, alert filter and simulation

Environment config

integration_id

Every order

Per-MID mapping

merchant_id

Interpreting which MID an alert or enrolment belongs to

Order record

order_id + your reference_id

PATCH updates and reconciliation

Alert record

alert_id

GET and PATCH on alerts

Step 2 — set up webhooks

Configure your endpoint in the dashboard under Settings → Webhooks (do this in both organisations). Subscribe to:

  • alert.created, alert.updated — network alerts and their resolution

  • enrolment.created, enrolment.updated — programme enrolment status changes

  • lookup.created, lookup.updated — digital receipt lookups and deflection outcomes

Your endpoint must be HTTPS and should return a 2xx within 20 seconds. Saving the endpoint generates a signing secret (whsec_...) — reveal it with the eye icon and store it with your API key.

Delivery contract

  • Payload:

    For alert events, data.object is the same alert object the Alerts API returns. Enrolment events use api_version: "v2" and return merchant_ids as an array.

  • Retries: if delivery fails, we retry up to 5 times over approximately two days (after 1 minute, 5 minutes, 30 minutes, 2 hours, then 12 hours). Retries of the same delivery keep the same X-Idempotency-Key header.

  • Deduplication: rely on the event id from the payload to process each event exactly once.

  • Health: endpoints that keep failing are automatically disabled and you are notified by email. Keep handlers fast — verify the signature, persist the event, enqueue processing, return 2xx.

  • Fallback: poll GET /v1/alerts/?status=ACTION_REQUIRED on a schedule so an outage on your side can never leave an actionable alert unseen.

Verify the signature

Every request includes an X-Signature header in the form t=<unix_timestamp>,v1=<hex_digest>, where the digest is an HMAC-SHA512 of "{timestamp}.{raw_body}" using your webhook secret. Reject requests whose timestamp is outside a small tolerance (for example five minutes) and whose signature does not match.

Full delivery details, sample payloads for every event type, and a Postman collection are in the webhooks guide.

Step 3 — send every order

Send each order to POST /v1/orders/ shortly after payment is captured. The request body is always a JSON array (even for one order), with up to 100 orders per request.

Every order in a full integration uses "type": "COMPLETE" and must include:

Field
Description

type

Must be "COMPLETE"

organisation_id

Your organisation ID

integration_id

Your CUSTOM_ORDERS integration ID

reference_id

Unique order identifier from your system

order_datetime

When the order was placed (ISO 8601)

order_number

Customer-facing order number

order_subtotal_amount_in_cents

Subtotal before tax

order_currency

ISO 4217 currency code

order_total_amount_in_cents

Total amount

order_status

OPEN_PENDING, OPEN_PENDING_RETURN, CLOSED_COMPLETE, CLOSED_CANCELLED or OTHER

Field sets per tool

One payload powers every tool. This table shows which fields each tool relies on beyond the required core above:

Tool
Fields

Alert matching (Ethoca, RDR reconciliation)

At least one transaction with amount_in_cents, currency, authorised_at, payment_method_type, authorisation_status; for cards also payment_method_card_brand, payment_method_card_last_4, and at least one identifier: acquirer_reference_number, authorisation_code or payment_method_card_bin

Consumer Clarity

order_datetime, order_number, order_subtotal_amount_in_cents, order_currency, order_total_amount_in_cents; refund_datetime on every refund; receipt extras (items, deliveries, order_*_url links, merchant profile) make the receipt materially better

Order Insight

At least one items[] entry with name; keep order_number to 25 characters or fewer (longer values are truncated in Order Insight responses)

First-Party Trust

customer_email, order_email, and at least one of device_ip_address, device_id, device_fingerprint

CE3.0

customer_email and at least one device identifier — on every order, so historical purchases qualify as evidence

Merchant information (multi-brand / per-MID receipts)

merchant_name, merchant_store_name, merchant_contact_phone, merchant_url when values differ per order; stable values can be configured as defaults in the platform instead

Your integration is configured with validation rules for the tools you have enabled, so missing fields are rejected with a MISSING_FIELD error naming the field and the rule — you will find out at submission time, not at dispute time.

Matching identifiers. For card transactions, send all three identifiers whenever available. If you cannot, at least one of these combinations must be present:

  • acquirer_reference_number (works on its own — the strongest identifier)

  • authorisation_code + payment_method_card_last_4

  • payment_method_card_bin + payment_method_card_last_4 + payment_method_card_brand + amount_in_cents + currency

Also send the transaction descriptor — with multiple MIDs, the billing descriptor confirms which MID's enrolment an alert belongs to.

Example: one order powering the full suite

Full COMPLETE order payload

For subscription MIDs, include a subscriptions entry (reference_id, interval, interval_price_in_cents, interval_currency, plus trial fields) and link items to it with subscription_reference_id. For digital goods, use a DIGITAL delivery with the digital_* field set — download timestamps and delivery IP are strong evidence.

The complete field reference — every field, type, validation rule and enum — is in the Orders API reference.

Handle the response

POST /v1/orders/ uses partial success: each order in the batch is processed independently.

  • Inspect errors[] for every batch; route failures to a retry queue keyed by reference_id.

  • There is no idempotency header — reference_id is your idempotency key. Retrying a request that already succeeded returns DUPLICATE_ORDER (or DUPLICATE_REFERENCE_ID under concurrent retries). Treat both as "already stored", not as failures.

  • A malformed request body (not an array, invalid types) returns a full-request 422 and no orders are processed.

  • On 429 or 5xx, retry the same payload with exponential backoff — duplicates are rejected safely.

Backfill before go-live. Submit your historical orders (not just new ones) before alert traffic is enabled, so the very first alert can match a transaction. For CE3.0, qualifying evidence comes from the cardholder's prior undisputed purchases in the 120–365 days before a dispute — backfilling up to 12 months of history, with customer_email and device identifiers, makes customers eligible from day one. Respect the 100-orders-per-request and 100-requests-per-minute limits when backfilling.

Step 4 — keep orders up to date

Send lifecycle changes to PATCH /v1/orders/{order_id} as they happen. This is what keeps the receipt data current and lets us detect invalid alerts (for example an alert for a transaction you already refunded) before you spend money resolving them.

When this happens in your system
Send

You issue a refund

A refunds entry (include refund_datetime — required for Consumer Clarity)

An item ships or is delivered

A deliveries update with the new physical_shipping_status and timestamps

A subscription is cancelled

A subscriptions update with status: "CANCELLED"

You receive a chargeback or inquiry directly

A disputes entry

The order is cancelled or returned

An order_status update

Notes:

  • PATCH is all-or-nothing: if any part fails validation, the whole update is rolled back with a 422.

  • Refunds and disputes are upserts by reference_id; on existing records amount_in_cents and currency (and dispute type) are immutable.

  • Deliveries and subscriptions can only be updated if they were created with the order; delivery type cannot change.

Step 5 — respond to alerts

This is the operational core of the integration. Alert behaviour differs by programme:

Enrolment type
How it arrives
What you must do

ETHOCA_ALERT

status: "ACTION_REQUIRED" with an action_required_deadline (typically around 48 hours)

Refund with your processor, then resolve the alert via the API — or accept the dispute

VERIFI_RDR

status: "RESOLVED" with transaction_refund_outcome: "REFUNDED" — the refund already happened at network level

Reconcile only: record the refund, stop fulfilment, cancel any subscription. Never refund again with your processor.

The Ethoca alert workflow

1

Receive the alert

Your webhook receives alert.created with status: "ACTION_REQUIRED":

Acknowledge with a 2xx immediately and process asynchronously.

2

Locate the order

When the alert matched one of your transactions, integration_transaction_id contains your transaction reference_id — look the order up directly in your own system, or via GET /v1/orders/?reference_id=<id>. merchant_id tells you which MID the alert belongs to.

If integration_transaction_id is null, fall back to the transaction fields on the alert (ARN, auth code, card last 4, amount, descriptor). Persistent unmatched alerts usually mean gaps in your order feed — investigate them.

3

Decide and act with your processor

Apply your policy (most merchants refund fraud alerts below a value threshold and review the rest). If you decide to refund:

  • Issue the refund through your payment processor for the alerted transaction.

  • Stop fulfilment and cancel any related subscription in your own system.

ChargebackStop cannot do this step for you on a CUSTOM_ORDERS integration — the refund must happen in your systems.

4

Resolve the alert before the deadline

Report the outcome so it reaches the issuer through Ethoca:

Action
Meaning for a Custom Orders integration

REFUND

Declares you have refunded the customer with your processor. Resolves the alert with transaction_refund_outcome: "REFUNDED". It does not move money.

ACCEPT_DISPUTE

You are not refunding; the dispute proceeds and you may fight it. Resolves with transaction_refund_outcome: "NOT_REFUNDED".

(CANCEL and REFUND_AND_CANCEL exist for integrations where ChargebackStop has processor or subscription access; with Custom Orders use REFUND or ACCEPT_DISPUTE.)

The response returns the alert with status: "RESOLVED". Resolved alerts cannot be actioned again (422 INVALID_ACTION).

5

Update the order

Record the refund on the order too, so future alerts and receipts reflect it:

You will also receive alert.updated events whenever status, transaction_refund_outcome or subscription_cancel_outcome change — including for resolutions made by your own team in the dashboard, and for RDR alerts. Alerts with status: "INVALID" were withdrawn or detected as invalid (for example, already refunded before the alert) — store them for reporting; no action is needed.

Step 6 — monitor deflection outcomes

Consumer Clarity, Order Insight, FPT and CE3.0 activity is visible as lookups — one record per time a network requested your order data:

  • lookup.created fires when an issuer/cardholder triggers a lookup against your enrolments.

  • lookup.updated fires when lookup_status or deflection_status changes.

Key fields on the lookup object:

Field
Values
Meaning

type

ETHOCA_CONSUMER_CLARITY, ETHOCA_FIRST_PARTY_TRUST, VERIFI_ORDER_INSIGHT, VERIFI_COMPELLING_EVIDENCE_3

Which product served the request

lookup_status

PENDING, SUCCEEDED, FAILED, TIMEOUT

Whether we answered the network successfully

deflection_status

NOT_ATTEMPTED, PENDING, SUCCEEDED, FAILED

Whether the dispute was deflected (CE3.0)

integration_transaction_id

Your transaction reference_id

Ties the lookup back to your order

Use deflection_status: "SUCCEEDED" as the positive CE3.0 deflection signal for reporting. A high rate of lookups with integration_transaction_id: null means the networks are asking about transactions your order feed doesn't cover — the fix is always more complete order data. You can also query history with GET /v1/lookups/ (Lookups API reference).

Optional — control RDR decisioning with rulesets

By default, RDR accepts and refunds every eligible Visa dispute on your enrolled BIN/CAIDs. If you want exceptions — for example, contest disputes above a value threshold — create a ruleset with the Rulesets API (your organisation key has rulesets:read / rulesets:write):

This example declines the automatic refund for disputes over $250, letting them proceed as normal disputes you can fight. Create rulesets before go-live if you need them — see the Rulesets API reference and resolution rules for details.

Test the integration end to end

Everything above works identically in your test organisation, with simulated network traffic. Use your test organisation's API key and IDs throughout.

1

Enable your test enrolments

Test enrolments are not activated by the real networks, so enable them via simulation and confirm the enrolment.updated webhook arrives:

2

Submit a test order

Send a COMPLETE order to your test integration with a known ARN (exactly 23 characters) and authorisation code (exactly 6 characters) on the transaction.

3

Simulate an actionable Ethoca alert

This fires a real alert.created webhook to your test endpoint. Note: the simulator does not run order matching inline, so integration_transaction_id may be null — exercise your fallback matching path here, and verify matched alerts against real traffic during go-live.

4

Resolve it

Run your full workflow: webhook → order lookup → (pretend) processor refund → PATCH /v1/alerts/{alert_id} with "action": "REFUND"PATCH the order with the refund. Confirm the alert.updated webhook shows status: "RESOLVED" and transaction_refund_outcome: "REFUNDED".

5

Simulate the rest of the suite

  • An RDR alert (RDR only supports RESOLVED or INVALID): confirm your handler records it without triggering a processor refund.

  • A lookup via POST /v1/simulate/lookups for each type you use: confirm lookup.created handling and your deflection reporting.

See the Simulations API reference for all options.

Sandbox acceptance checklist

Go-live checklist

1

Create live credentials and webhooks

Create the live organisation API key and configure the production webhook endpoint on the live organisation; store both secrets separately from test.

2

Backfill order history

Backfill order history (12 months where possible) into the live integration before alert traffic is enabled.

3

Enable real-time feeds

Switch on the real-time order feed and lifecycle updates.

4

Confirm enrolments are enabled

Confirm every enrolment reports status: "ENABLED" (via enrolment.updated webhooks or your dashboard) before treating a programme as live.

5

Verify alert matching

Verify the first live alerts arrive with integration_transaction_id populated — unmatched alerts at go-live mean feed gaps.

6

Cover the Ethoca deadline

Confirm your operations rota covers the Ethoca deadline window (including weekends) and that deadline alerts page a human.

7

Verify refund workflows

Verify the first refunds flow end to end: processor refund → alert resolved → order updated.

8

Monitor lookups

Monitor lookups in the first weeks: lookup_status: "SUCCEEDED" with your orders attached, and CE3.0 deflection_status outcomes.

Error handling reference

All APIs use the same error envelope:

Situation
Code
Handling

Missing/invalid API key

UNAUTHORISED (401)

Check the key and the environment it belongs to

Key lacks an ability

FORBIDDEN (403)

Recreate the key in the dashboard

Rate limited

RATE_LIMITED (429)

Exponential backoff with jitter; no Retry-After header is sent

Order already exists

DUPLICATE_ORDER / DUPLICATE_REFERENCE_ID (in errors[])

Treat as already stored

Wrong order type for integration

INVALID_ORDER_TYPE

COMPLETE orders require the CUSTOM_ORDERS integration

Integration not found/accessible

INVALID_INTEGRATION

Check integration_id and organisation_id

Field required by your enabled tools

MISSING_FIELD

The message names the field and the rule (e.g. visa_compelling_evidence_3_0)

Whole-request schema failure

VALIDATION_* (422)

Fix payload shape/types; nothing was processed

Actioning a resolved alert

INVALID_ACTION (422)

Fetch the latest alert state before actioning

Simulating against a live org

SIMULATION_NOT_ALLOWED (422)

Simulations work only on test organisations

One inconsistency to code around: PATCH /v1/orders/{order_id} returns 404 as {"detail": "Order with ID ord_x not found"} rather than the standard errors[] envelope.

Last updated

Was this helpful?