DOCUMENTATION / API REFERENCE

Purchase tracking and acquisition cost

Connect verified backend receipts, review a test purchase, and measure customers and costs including fees.

Markdown

Connect product purchases

Use this flow for purchases of the advertised product. Advertising balance top-ups are funding, never product revenue. Cometly and Meta attribution remain separate measurements of overlapping sales; do not add their revenue to receipt revenue.

MarketingRouter currently accepts receipts from a merchant payment backend. That backend must verify the checkout provider's signed webhook or retrieve its payment record before calling this API. A success-page visit, browser pixel, agent assertion or payment-created event is not proof of payment. Only submit settled/succeeded payments, then submit later refunds and disputes. No checkout-specific adapter is installed automatically.

The returned proof level is merchant_backend_confirmed: MarketingRouter authenticates the backend's statement, but does not independently retrieve the payment from the processor. Choosing your first checkout adapter and validating a real checkout remain deployment steps.

Owner setup, once per workspace

An agent with a live campaigns:read key reads GET /api/v1/checkout and follows next_action. Send the owner to /dashboard?tab=measurement, then Checkout receipts. The owner creates dedicated test and live backend credentials using POST /api/v1/checkout with {"expected_revision":0}. Only an owner session can create or rotate them.

The keys appear only once. Store them in the merchant backend's secret store; never in browser code, URLs, prompts or the agent runtime. Normal MarketingRouter API keys and owner sessions cannot submit receipts. To replace keys, read the current revision and POST it as expected_revision. Both old keys stop working immediately, and previous campaign test approvals become invalid. If the create response was lost, read the revision and rotate; the original secret cannot be recovered.

For webhook integration, keep the provider's webhook endpoint on your own backend. Verify its signature, deduplicate its event, look up the correct campaign from server-held attribution metadata, then submit the normalized receipt below. MarketingRouter does not accept arbitrary processor webhook payloads directly. Retry our receipt request with the same event ID and identical body after uncertain responses.

Submit a receipt from the verified backend

POST /api/v1/checkout/receipts uses Authorization: Bearer $MR_CHECKOUT_TEST_KEY for test receipts or $MR_CHECKOUT_LIVE_KEY for actual settled payments. The credential chooses the mode; no mode field is accepted. Body limit is 16 KiB. Use integer USD cents. Only USD is supported; do not convert other currencies silently.

{
  "event_id": "checkout_evt_001",
  "order_id": "checkout_order_001",
  "customer_id": "checkout_customer_001",
  "payment_id": "checkout_payment_001",
  "campaign_id": "REPLACE_WITH_CAMPAIGN_UUID",
  "revision": 1,
  "paid_at": "REPLACE_WITH_ACTUAL_PAYMENT_ISO_TIMESTAMP",
  "amount_cents": 4900,
  "refunded_cents": 0,
  "disputed": false,
  "currency": "USD"
}

Identifiers accept letters, digits, underscores, periods, colons and hyphens, up to 160 characters. Use stable opaque IDs, namespaced by checkout provider. Do not send names, email addresses, card details or other personal payment data. customer_id is hashed with the workspace identity before storage. Keep the same customer ID across repeat purchases. Stable IDs distinguish customers; changing IDs creates incorrect counts.

Keep campaign, customer, payment, original amount and original paid_at immutable for an order. A payment can belong to only one order in each mode. paid_at must be on or after campaign creation, and no more than five minutes in the future. Live receipts require a live campaign; test receipts can refer to a live draft before any ad spend. Campaign assignment is the merchant's attribution decision, not independently inferred by MarketingRouter.

amount_cents is the original amount of product revenue you report. Use the same accounting basis for every receipt, excluding taxes/shipping if your revenue definition excludes them. Do not send advertising costs here. API responses do not classify tax or shipping for you.

Identical event_id retries return deduplicated:true; changing the payload under an existing event ID returns a conflict. Keep increasing revision for each change to an order. Use a new event ID for a new revision. Send cumulative refunded_cents, not the latest refund delta. Refunds cannot exceed the original amount. Disputes exclude the entire order's revenue; disputed:true is sticky. This version does not restore reversed disputes or reduce cumulative refunds. Request operator reconciliation for those cases; do not create replacement orders.

Older revisions are accepted without changing the current order (applied:false). Test receipts never enter live economics, credit an advertising balance, or forward a Meta conversion. Continue the separate destination tracking flow with its own event deduplication for optimization signals.

Prove tracking before purchase-campaign delivery

  1. Create the exact live campaign plan. Preparing its non-delivering draft does not require a purchase test.
  2. Run your checkout provider's test payment through the merchant backend, submitting a receipt with the dedicated test key and this campaign ID.
  3. The owner checks the actual test payment, amount, customer and campaign in the backend. In the campaign's Purchase tracking section, enter the test order ID and confirm. The API equivalent is POST /api/v1/campaigns/{id}/checkout-validation with {"test_order_id":"checkout_order_001","acknowledge_receipt_checked":true} using an owner session.
  4. Read GET /api/v1/campaigns/{id}/economics. checkout_ready:true proves a recent receipt was received and reviewed for this exact plan and current keys. It is not an independent processor audit or permission to spend.
  5. Complete the existing pixel, funding, advertiser and owner-approval checks before launch.

The test receipt must be no more than seven days old when reviewed and have no refund/dispute. Review is valid for 30 days and bound to the campaign plan, destination and credential revision. New campaign plans or credential rotation require new test receipts. A test key can submit only test data and cannot manufacture live revenue.

Live purchase launch, resume and budget increases return checkout_test_required until ready. Pause and budget decreases remain available without this check. Sandbox and non-purchase objectives do not require it. A failed check does not automatically pause an already active campaign; use explicit controls if tracking stops working.

Read acquisition economics

GET /api/v1/campaigns/{id}/economics accepts a campaigns:read key in the campaign's allowed mode. Reconcile Meta delivery first to refresh spend. The response is lifetime-only; date-filtered third-party attribution belongs to the measurement report.

FieldMeaning
media_spend_centsLatest observed Meta media spend, or null when unknown.
ordersReceived live orders, including fully refunded/disputed orders.
paying_customersDistinct recorded customer IDs with positive net revenue in this campaign. Repeat orders count once.
gross_revenue_centsOriginal amounts from received live receipts.
refunded_revenue_centsCumulative recorded refunds.
revenue_centsNet revenue after refunds; disputed orders contribute zero.
service_fee_cents / payment_cost_centsOwner-reconciled advertising costs for the exact spend checkpoint; null until reconciled.
total_acquisition_cost_centsMedia spend + service fees + advertising payment costs.
cost_per_paying_customer_centsTotal acquisition cost divided by distinct paying customers; null if any cost is unknown or no paying customers exist.
new_customer_cac_centsAlways null: recorded buyers are not proven new customers.

Counts cover only receipts received. A zero count is not proof no payments happened; monitor your backend's webhook delivery and compare against checkout records. Purchases assigned to different campaigns are not deduplicated across those campaigns. Review revenue_verification, cost_verification, observed_at, blockers and warnings before making a spending decision. A test receipt is excluded from all live totals.

Reconcile fees honestly

This version uses an owner-recorded cost checkpoint, not automatic processor settlement. In the campaign's Cost breakdown → Reconcile actual fees, record actual advertising service fees and payment costs allocated to this campaign's displayed lifetime media spend. Do not include the product checkout's processing fees or double-count top-up fees across campaigns. An explicit zero is appropriate only when verified.

The API is owner-only PUT /api/v1/campaigns/{id}/economics:

{
  "media_spend_cents": 10000,
  "service_fee_cents": 300,
  "payment_cost_cents": 320,
  "receipt_reference": "advertising-invoice-001",
  "acknowledge_actual_costs": true
}

These example fees are accounting observations, not MarketingRouter pricing. The media amount must match the latest stored Meta observation exactly or returns cost_spend_mismatch. These fields never charge a fee, grant allowance or release funds. Updated media spend invalidates the checkpoint so all-in costs return null until reconciled again. Pause does not settle final costs; spend and refunds can arrive later. Cost per customer is a measurement, not an enforced cap.

Act within the existing approval

Read media buying controls. Use the latest control revision and a stable Idempotency-Key for pause, resume or budget changes. No analytics or checkout connection grants additional spending authority. Owner budget ceilings, funding checks, exact plan approval and deployment gates continue to apply. On uncertain control responses, reconcile the same command before issuing another.

Recovery and capacity

Stop receipt retries on identity/revision conflicts and investigate the merchant mapping. Never fabricate a new order to bypass a conflict. A checkout_key_revoked response needs current backend credentials. On checkout_revision_conflict, read the latest credential revision before owner rotation. On checkout_test_required, review the specific campaign's test flow. Unknown monetary values must remain null in downstream analysis.

The initial receiver is bounded to 10,000 orders and 50,000 distinct events per workspace across test/live modes. checkout_capacity requires operator review; do not retry indefinitely. There is no historical pre-campaign import, arbitrary currency support, checkout auto-install, processor dispute-reversal workflow or automated fee settlement in this release.