API reference
Lifecycle events
Report what happens after checkout — intake, the clinician's decision, refills, refunds — so commissions follow the patient's real lifecycle. Provider-neutral: the payment gateway is just a field.
Report an event
POST
/v1/eventswrite scopeSend one event, or up to 100 as `{ "events": [...] }` (processed in order). Each event changes commission according to the program's lifecycle settings.
Body parameters
| eventIdreqstring | Unique per event. Idempotency key — resends are no-ops. |
| typereqenum | `intake_submitted` · `rx_approved` · `rx_declined` · `refill_shipped` · `subscription_cancelled` · `refund` · `chargeback` |
| orderIdreqstring | Same id as `POST /v1/conversions`. For an intake before any order, your intake id. |
| occurredAtreqISO 8601 | When it happened, with timezone offset. |
| refillNumberint | Required for `refill_shipped` (1, 2, 3 …). On a refund, targets that refill only. |
| amountCentsint | Refill amount, or amount refunded (partial refunds reduce commission proportionally). |
| paymentProviderstring | e.g. `stripe` · `nmi` · `whop`. Stored for reporting only. |
| subscriptionIdstring | Your subscription id. |
| referralCodestring | `intake_submitted` only: attribution for the intake. |
| clickIduuid | `intake_submitted` only: attribution for the intake. |
Response
json
{
"eventId": "evt_rx_10422",
"outcome": "released",
"details": { "releasedCount": 1 },
"duplicate": false
}- Outcomes: `released`, `rejected`, `renewal_recorded`, `reversed`, `reduced`, `bounty_recorded`, `recorded`, plus no-op outcomes such as `no_conversion`, `already_released`, `recurring_disabled`, `beyond_recurring_limit`. Every `200` is final.
- A `5xx` means the event was not processed — retry it (for a batch, from `failedEventId`).
- Order of arrival doesn't matter: a conversion that arrives after its `rx_approved` is released immediately.
- Never send health data. Ids, amounts, types and timestamps only.