Skip to content

Developer Integration API Reference

Connect a custom storefront to Refermate: the capture script, the server postback API for orders, refunds, and subscriptions, response codes, and how to verify tracking.

Base URL https://partners.refermate.com · Markdown version · Create a merchant account

(01)

How it works

  1. You verify your storefront domain once: publish the capture script with your store's data-rm-store-verification attribute on your homepage, and Refermate checks for it. Only then can you create the integration.
  2. A creator shares a Refermate link. Refermate records the click and sends the shopper to your site with an rm_click query parameter.
  3. The capture script stores that value in a first-party cookie on your site.
  4. At checkout you save the click ID with the order.
  5. When the order is paid, your server posts it to Refermate. Money moves only on these server postbacks, never on browser events.
  6. You approve conversions in Partners. Refermate bills your saved payment method after the refund hold and pays the creator.

(02)

Capture script

Add this to the <head> of every page a creator link can land on.

<script src="https://partners.refermate.com/api/pn/sdk/v1.js" data-rm-consent-mode="explicit" data-rm-max-age-days="30" defer></script>
  • Without a consent attribute, the script assumes your consent manager loaded it after consent. With data-rm-consent-mode="explicit", it stores and reads nothing until you call window.RefermateCapture.grantConsent(), and that holds on every page: call it on each page load once the shopper has accepted, including checkout, or getClick() returns null. The click is captured only on the landing page, so it is lost if consent arrives after the shopper leaves it.
  • A consent manager can decide before the deferred script loads. Keep the decision and call grantConsent() once window.RefermateCapture exists, for example from the script tag's load event.
  • window.RefermateCapture.getClick() returns the stored click ID for your checkout.
  • The cookie is _refermate_click, host-only and SameSite=Lax. data-rm-max-age-days asks for 1 to 365 days (default 30), but browsers can expire it sooner: Safari keeps cookies set by scripts for at most 7 days. The last click wins.
  • If your router rewrites the URL before deferred scripts run, drop defer.

(03)

Authentication

Send your secret postback key as Authorization: Bearer <key> (or X-Refermate-Postback-Key). Bodies are JSON, up to 16 KiB. Call these endpoints only from your server; the key must never reach a browser.

(04)

Endpoints

POST /api/partner-network/postbacks/<public-tracking-key>/conversions

Report a paid one-time order that carries a Refermate click. Post only orders with a click; an order without one is rejected with 422 missing_referral_click.

FieldDescription
order_idRequiredYour stable order ID, up to 500 characters. It is the idempotency key: resending the same order is safe.
click_idRequiredThe rm_click value the capture script stored for this shopper. An order without one is rejected with 422 missing_referral_click.
currencyRequiredThree-letter currency code. Only USD is accepted.
order_subtotal_centsRequiredOrder subtotal in cents, a whole number of 0 or more.
occurred_atRequiredWhen it happened, in ISO 8601 with an explicit offset (Z or ±HH:MM), for example 2026-09-28T17:05:00.000Z. Any number of fractional digits is accepted; Refermate keeps milliseconds and drops the rest. JavaScript toISOString(), .NET "o", Java Instant.toString(), and Python isoformat() on a timezone-aware datetime all qualify. A time without an offset is rejected.
eligible_amount_centsOptionalThe commissionable part of the subtotal. Defaults to the subtotal and cannot exceed it.
line_itemsOptional[{ product_id, amount_minor_units, quantity }], summing to the eligible amount. Required when the program pays per product.
order_nameOptionalA customer-facing order number.
customer_idOptionalYour customer ID, for your own reporting.
discount_codeOptionalA discount code used on the order.
metadataOptionalAn object of your own data, up to 4 KiB.
testOptionaltrue only for the verification order from your setup page.
{
  "click_id": "a1B2c3D4e5F6g7H8",
  "currency": "USD",
  "eligible_amount_cents": 10000,
  "occurred_at": "2026-09-28T17:05:00.000Z",
  "order_id": "ORDER-1001",
  "order_name": "#1001",
  "order_subtotal_cents": 10000
}

POST /api/partner-network/postbacks/<public-tracking-key>/reversals

Report a refund or cancellation of a one-time order. Leave out amount_refunded_cents, or send the full subtotal, to reverse the order. For a partial refund, Refermate reduces the commission in proportion, but only within the program's refund hold; after it, a partial refund returns 422 partial_refund_not_adjusted and only a full refund reverses. A refund that arrives after Refermate has billed you for the commission returns 422 paid_conversion_not_auto_reversed and reverses nothing; contact support to settle it.

FieldDescription
order_idRequiredThe same order ID you sent to conversions.
amount_refunded_centsOptionalTotal refunded on this order so far, in cents, on the same basis as order_subtotal_cents (leave out refunded tax and shipping). Send the running total, not the latest refund. Resending a total already recorded returns that first answer, even after you are billed or the order is put on hold. Requires occurred_at. A new total lower than one already recorded returns 409 refund_amount_conflict unless its occurred_at is earlier. Above the subtotal returns 422 invalid_amounts.
occurred_atOptionalWhen it happened, in the same format: ISO 8601 with an explicit offset. Defaults to when we receive the request; send it when you replay a late event.
reasonOptionalA short reason such as refunded or cancelled.
{
  "occurred_at": "2026-10-02T09:30:00.000Z",
  "order_id": "ORDER-1001",
  "reason": "refunded"
}

POST /api/partner-network/postbacks/<public-tracking-key>/v2/recurring/relationships

Bind a new subscription to the Refermate click that started it. Send this once, when the subscription is created. Add a subscription commission rule for the product in Partners first: a bind with no matching rule returns no_matching_subscription_rule and keeps that subscription at zero commission, even after you add a rule.

FieldDescription
event_idRequiredYour unique ID for this event; resending it is safe.
relationship_idRequiredYour stable subscription ID.
click_idRequiredThe rm_click value for this shopper.
product_idRequiredThe subscribed product.
price_idOptionalThe subscribed price or plan.
currencyRequiredOnly USD is accepted.
environmentRequiredAlways live for production traffic.
occurred_atOptionalWhen it happened, in the same format: ISO 8601 with an explicit offset. Defaults to when we receive the request; send it when you replay a late event.
{
  "click_id": "a1B2c3D4e5F6g7H8",
  "currency": "USD",
  "environment": "live",
  "event_id": "evt-sub-1001-created",
  "occurred_at": "2026-09-28T17:05:00.000Z",
  "product_id": "plan-pro",
  "relationship_id": "sub-1001"
}

POST /api/partner-network/postbacks/<public-tracking-key>/v2/recurring/billing-events

Report each invoice of a bound subscription, paid or not. Never send a click here: the relationship already names it.

FieldDescription
event_idRequiredYour unique ID for this event.
relationship_idRequiredThe subscription ID you bound.
invoice_idRequiredYour invoice ID.
payment_stateRequiredpaid, failed, open, void, or uncollectible. Only paid can earn a reward.
amount_paid_minor_unitsRequiredAmount paid, in cents.
eligible_amount_minor_unitsOptionalThe commissionable part. Defaults to the amount paid and cannot exceed it.
product_idRequiredThe billed product. A product or price different from the bound one holds the subscription for review.
price_idOptionalThe billed price or plan.
currencyRequiredOnly USD is accepted.
environmentRequiredAlways live for production traffic.
occurred_atRequiredWhen it happened, in ISO 8601 with an explicit offset (Z or ±HH:MM), for example 2026-09-28T17:05:00.000Z. Any number of fractional digits is accepted; Refermate keeps milliseconds and drops the rest. JavaScript toISOString(), .NET "o", Java Instant.toString(), and Python isoformat() on a timezone-aware datetime all qualify. A time without an offset is rejected.
{
  "amount_paid_minor_units": 1999,
  "currency": "USD",
  "environment": "live",
  "event_id": "evt-inv-1001-paid",
  "invoice_id": "inv-1001",
  "occurred_at": "2026-09-28T17:05:00.000Z",
  "payment_state": "paid",
  "product_id": "plan-pro",
  "relationship_id": "sub-1001"
}

POST /api/partner-network/postbacks/<public-tracking-key>/v2/recurring/reversals

Report a full refund of one subscription invoice. It takes no amount: a body with a refund amount returns 422 unsupported_reversal_type and reverses nothing.

FieldDescription
event_idRequiredYour unique ID for this event.
relationship_idRequiredThe subscription ID.
invoice_idRequiredThe refunded invoice.
reasonOptionalA short reason.
environmentRequiredAlways live for production traffic.
occurred_atOptionalWhen it happened, in the same format: ISO 8601 with an explicit offset. Defaults to when we receive the request; send it when you replay a late event.
{
  "environment": "live",
  "event_id": "evt-inv-1001-refunded",
  "invoice_id": "inv-1001",
  "occurred_at": "2026-10-02T09:30:00.000Z",
  "reason": "refunded",
  "relationship_id": "sub-1001"
}

POST /api/partner-network/postbacks/<public-tracking-key>/v2/recurring/relationships/end

Report that a subscription ended. Later invoices for it are rejected.

FieldDescription
event_idRequiredYour unique ID for this event.
relationship_idRequiredThe subscription ID.
reasonOptionalA short reason.
environmentRequiredAlways live for production traffic.
occurred_atOptionalWhen it happened, in the same format: ISO 8601 with an explicit offset. Defaults to when we receive the request; send it when you replay a late event.
{
  "environment": "live",
  "event_id": "evt-sub-1001-ended",
  "occurred_at": "2026-12-28T17:05:00.000Z",
  "reason": "canceled",
  "relationship_id": "sub-1001"
}

(05)

Responses

Every response is JSON with ok and a machine-readable reason, for example {"ok": true, "reason": "recorded", "transaction_id": 123}. Created records add transaction_id, conversion_id, binding_id, or event_id. Branch on the status and reason, never on wording.

StatusMeaning
200Accepted, including an exact replay of an earlier request (for example duplicate_order). A replayed recurring event returns the first delivery's reason and status with replayed: true.
400The body is not valid JSON or is missing a required field (invalid_payload, json_required, unexpected_click_id). Fix the request; do not retry it.
401Missing or wrong postback key.
403The integration is disabled or the store is archived.
404The subscription, invoice, or click named in a recurring request does not exist.
409The same ID was sent earlier with different content (duplicate_order_conflict, duplicate_event_conflict, refund_amount_conflict), or the environment does not match.
410A verification test link expired.
413The body is larger than 16 KiB.
422The request is valid but cannot earn, for example missing_referral_click, referral_click_already_converted, unsupported_pricing_currency, invalid_occurred_at, relationship_ended, or partial_refund_not_adjusted. Do not retry. pricing_history_ambiguous means the purchase time falls within the same second (or millisecond) as a change to your commission rules, so Refermate cannot tell which rates applied; resending the same body gets the same answer, so resend occurred_at with milliseconds or contact support. paid_conversion_not_auto_reversed means a refund came after the commission was billed, so contact support.
423active_hold: the order is under a dispute or review hold, so the refund changed nothing. Resend the same body after the Retry-After delay (one day, also in retry_after_seconds); it succeeds once the hold resolves.
5xxUsually temporary: retry the same body with backoff. 503 means pricing history is briefly unavailable.
  • Retry only 5xx responses, network errors, and a 423 active_hold after its Retry-After, with the same body.
  • One click backs one one-time order. A second order on the same click returns referral_click_already_converted.
  • Only USD orders earn today.
  • occurred_at may be at most 5 minutes in the future. A paid order may be at most the program's attribution window plus 7 days old; refunds and subscription events may be up to 372 days old.

(06)

Verify your integration

Verify your domain first. On your Developer Integration setup page, copy the capture tag, which carries your store's data-rm-store-verification attribute, publish it on your homepage, and choose "Verify domain". Refermate loads https://<your-domain>/ over HTTPS, following up to three redirects on the same domain or its www. twin, and looks for that exact tag; you can create the integration only after it passes, and leaving the attribute in place is harmless. If the homepage cannot be checked, an approved store claim for the exact domain also verifies it. Then choose "Create test link". Open the link on your site, place an order, and post it with "test": true and the rmv_ click ID the script stored. A 200 test_verified response turns tracking on. Test orders never create money.