Skip to main content

Event Types

VitaRelay emits the core order and intake events below. Every order/intake.reviewed payload includes event (the type) and occurred_at (ISO 8601 timestamp); the newer intake.submitted event uses the versioned envelope shown in its section. Storefront integrations also receive the full order lifecycle (order.cancelled, order.fulfilled, order.payment_failed) and subscription lifecycle events. Deliveries generated by the sandbox also include "sandbox": true.
In live, order_id, patient_id, and escript_id are UUIDs and order_number is the real order number. In sandbox, ids look like sandbox_ord_…, sandbox_pat_…, and sandbox_int_….

Order events

Every order event (order.paid, order.shipped, order.delivered, order.cancelled, and the rest) also carries the patient and the order’s lines, so you can tell what was bought and by whom without a second call:
  • patient_id: the VitaRelay patient id (the id POST /patients returned; the same id every subscription.* event carries). Save it next to your own user record when you create the patient.
  • items: one entry per order line: item_kind (product or custom), item_id, name, quantity, and product_id for products. For a product, item_id and product_id are the catalog product id (the value POST /orders accepts as product_id). For a clinic service (custom), item_id is the service’s id, the id listed under custom_products in GET /shop.

order.invoiced

Fires when an order that is billed on an invoice (rather than charged to a card) is added to an invoice. It carries invoice_id, invoice_number, issued_on and due_on alongside the usual order fields. The order is not paid yet: order.paid follows when the invoice payment is recorded, with paid_via: "invoice".

order.paid

Fires when the order is paid — either the clinic’s card-on-file charge succeeds or, for a patient_checkout order, the patient’s payment via POST /orders/{id}/pay succeeds.

order.shipped

Fires when the order ships and tracking is attached.

order.delivered

Fires when the carrier reports delivery.

order.exception

Fires when the carrier reports a delivery problem (failed attempt, return to sender, address issue, and similar).

Intake events

Subscription events

Subscription webhooks use the versioned envelope and may include: subscription.created, subscription.updated, subscription.paused, subscription.resumed, subscription.canceled, subscription.renewed, subscription.payment_failed, and subscription.rx_hold. shop.item.updated fires when subscription settings change. Every subscription event’s data includes: subscription_id, patient_id, item_kind, item_id, quantity, cadence, status, paused_reason, next_charge_at. Event-specific extras: reason (paused), skipped_next (updated), order_id + charged_cents (renewed), order_id + held_item_count (rx_hold), and for subscription.payment_failed: order_id, attempt, max_attempts, next_retry_at, final. subscription.payment_failed fires on every failed attempt (retries after 2 and 3 more days). The third failure sets final: true, next_retry_at: null, and also emits subscription.paused with reason: "payment_failed".
subscription.renewed, subscription.payment_failed, and subscription.rx_hold are never emitted while patient billing is in dry-run mode (no real charge happens). Created/updated/paused/resumed/canceled events emit normally in dry-run.

intake.reviewed

Intake reviewed / prescription signed. Fires the moment a prescriber signs the escript — this is the “Rx cleared” signal you should key fulfillment off of.
If you placed the order before the prescription existed (the order is submitted), signing is followed by a check that the signed product and quantity match your order. Only then does the order become processing and go to the pharmacy. A mismatch holds the order for VitaRelay review, so for those orders follow the order’s status, not just this event. See Intakes and prescriber review.

intake.submitted

Fires the moment an intake is submitted — by the patient on their hosted intake link, or by your app through POST /intakes or the referral intake/submit. When the intake completes an order’s waiting intake, the order moves to prescriber review and the prescription request is sent to the doctor network. Use the event to know the intake is in. PHI-free: it carries ids, category, and status only — never the patient’s answers. This event uses the versioned envelope (type + event + api_version + created_at + data).

Sandbox deliveries

Events generated by the simulated sandbox lifecycle are identical in shape but carry "sandbox": true and sandbox ids:
Never treat a payload with "sandbox": true as a real clinical or financial event.