Webhooks
Webhooks let you receive real-time HTTP notifications when events happen in RxScale. Instead of polling for changes, register a webhook URL and RxScale will send you a POST request whenever an event occurs.How Webhooks Work
- Register a webhook subscription with your target URL and desired event type.
- Receive POST requests to your URL when events occur.
- Verify the webhook signature to ensure the request is authentic.
- Respond with a
2xxstatus code to acknowledge receipt.
Webhook Payload Format
All webhook payloads follow the same envelope structure:Processing Events Idempotently
Pharmacy order and stock events (pharmacy_order_created, pharmacy_order_updated, pharmacy_sku_stock_updated) do not describe a change. Each payload is a complete snapshot of the pharmacy order or pharmacy SKU, built at the moment the delivery is sent. There is no event ID. As a result:
- The same state can reach you more than once — for example when a delivery is retried, or when several changes happen in quick succession.
pharmacy_order_updatedcan arrive before thepharmacy_order_createdof the same order — for example when the first delivery ofpharmacy_order_createdfailed and is retried later.pharmacy_order_updateddoes not say what changed.
- Use
data.uidas the key and upsert: create the record if you don’t know it yet, whichever event arrives first. - Treat every payload as the latest full state and replace your stored copy with it. To find out what changed, compare it with what you stored — for example
statusorshipments. - Skip a payload whose
data.updated_atis older than the value you stored. It is an older snapshot that arrived late. - Make sure that processing the same payload twice is harmless.
- Do not deduplicate on
timestamp. It is set per delivery attempt: a retry carries a new value, while two different updates sent in the same second share one.
appointment_reminder_due and patient_doctor_meeting_updated carry the data captured when the event occurred, not a snapshot built at delivery time. For meeting events, see Delivery and Idempotency.Registering Webhooks
You can register webhooks through:- Pharmacy Portal — Navigate to API Access in the sidebar. If you manage multiple pharmacy groups, select the group from the dropdown at the top of the page.
- External Pharmacy API —
POST /v1/external_pharmacy_api/webhooks/ - Management API —
POST /v1/management/notification-subscriptions/
webhook_secret in the creation response, whether you register through the External Pharmacy API, the Pharmacy Portal or the Management API. It is shown only once, so store it securely: you need it to verify payload signatures (see Security).
Management API subscriptions can additionally send a custom request header you configure (header_key / header_value), for example an API key your endpoint already checks.
Retry Policy
Successful and Failed Deliveries
A delivery counts as successful as soon as your endpoint responds with any2xx status code — even if your own processing of the payload fails afterwards. Store the payload first, respond, and do heavy work asynchronously.
A delivery counts as failed when:
- your endpoint responds with any other status code — including
3xx(redirects are not followed) and every4xx, such as413 Payload Too Large; - your endpoint does not respond within 30 seconds;
- the connection cannot be established or the TLS handshake fails (for example because of an invalid certificate).
Retries
Failed deliveries are retried with exponential backoff: the first retry follows after roughly 10 seconds, and the wait grows to at most about 10 minutes between attempts. After 5 attempts in total, the delivery is dropped. There is no dead-letter queue and no way to replay a dropped delivery. Each attempt builds the payload again, so a retry carries the current state and a newtimestamp.
If deliveries were dropped — for example after an outage of your endpoint — reconcile through the External Pharmacy API:
- List orders with
GET /v1/external_pharmacy_api/pharmacy_orders/. Thestart_dateandend_datefilters apply to the order’s creation time. - Fetch the current state of an order with
GET /v1/external_pharmacy_api/pharmacy_orders/{pharmacy_order_uid}. The response is built from the same data as the webhook payload. - For stock levels, list your SKUs with
GET /v1/external_pharmacy_api/pharmacy_skus/.
Delivery Logs
Every delivery attempt for the subscriptions of your pharmacy group — successful or failed — is listed in the Pharmacy Portal under API Access → Webhook Delivery Logs, with the response status code or the error. A dropped delivery is shown there as a permanent failure.Payload Size
There is no fixed size limit, and payloads are never truncated. For subscriptions registered through the External Pharmacy API or the Pharmacy Portal, order payloads include the signed prescription PDF inline, Base64-encoded indata.prescription_file.content_base64 — never as a link. It is one PDF per order, sent in pharmacy_order_created and in every pharmacy_order_updated. prescription_file is null for orders that contain only over-the-counter products. Organisation-level deliveries (Management API) do not include prescription_file.
Payloads are typically a few hundred kilobytes, but uploaded or externally signed prescription PDFs can be much larger. Configure your endpoint — and any proxy or framework in front of it — to accept request bodies of at least 10 MB. A 413 response is a failed delivery like any other: it is retried and then dropped.