Webhook Events
RxScale sends webhooks for the following event types:| Event Type | Description |
|---|---|
pharmacy_order_created | A new pharmacy order was created and assigned to your pharmacy |
pharmacy_order_updated | An existing pharmacy order’s status changed |
pharmacy_sku_stock_updated | A pharmacy SKU’s stock level changed |
appointment_reminder_due | A scheduled appointment reminder became due |
patient_doctor_meeting_updated | A patient-doctor meeting changed lifecycle state |
HTTP Headers
Every webhook request includes the following HTTP headers:| Header | Description |
|---|---|
Content-Type | Always application/json |
X-Webhook-Event | The event type (e.g. pharmacy_order_created) |
X-Webhook-Signature | HMAC-SHA256 signature of the request body (see Security) |
pharmacy_order_created
Sent when a new pharmacy order is created and assigned to your pharmacy.Pharmacy orders are created for over-the-counter (OTC) purchases too, not only for prescription-based orders — any fulfillment routed to your pharmacy triggers this event, whether or not it includes a prescription. For an OTC-only order,
data.doctor_data and data.prescription_file are null, and data.prepaid is 0.status values: init, waiting for pharmacy, pending review, in-progress, ready_for_pickup, completed
Payload Example
{
"event_type": "pharmacy_order_created",
"timestamp": 1711900000,
"payload_version": "1",
"data": {
"uid": "po-abc123",
"status": "init",
"name": "#1001",
"data": {},
"external_status": "OPEN",
"created_at": 1711899000,
"updated_at": 1711899000,
"deleted_at": null,
"pharmacy": {
"uid": "ph-xyz",
"display_name": "City Pharmacy"
},
"order": {
"uid": "ord-123",
"delivery_address": {
"first_name": "Max",
"last_name": "Mustermann",
"street": "Hauptstr.",
"house_number": "1",
"zip_code": "10115",
"city": "Berlin",
"country": "Germany",
"additional_address": null,
"province": null
},
"invoice_address": {
"first_name": "Max",
"last_name": "Mustermann",
"street": "Hauptstr.",
"house_number": "1",
"zip_code": "10115",
"city": "Berlin",
"country": "Germany",
"additional_address": null,
"province": null
},
"shipping_costs_amount": 499,
"shipping_costs_currency": "EUR",
"priority": 5
},
"delivery_type": {
"uid": "dt-001",
"display_name": "Standard Shipping",
"identifier": "standard"
},
"shop_shipping_methods": [
{
"uid": "ssm-001",
"display_name": "DHL Standard",
"external_id": "shopify-standard",
"pharmacy_mapping": {
"pharmacy_uid": "ph-xyz",
"shipping_method_identifier_for_pharmacy": "DHL_STANDARD"
}
}
],
"order_items": [
{
"uid": "oi-789",
"amount": 1,
"sku": {
"uid": "sku-456",
"display_name": "Medication X 100mg",
"pzn": "12345678",
"product_uid": "prod-789",
"product_display_name": "Medication X",
"standard_selling_unit": 1.0,
"unit": "ml",
"product_handle": "medication-x"
},
"pharmacy_sku": {
"uid": "psku-456",
"external_id": "EXT-001",
"price": 1299,
"stock": 50
},
"total_paid_amount": 1299
}
],
"payouts": [
{
"status": "projected",
"amount": 999,
"currency": "EUR",
"component_type": "item_rest",
"routing_description": "Medication X 100mg item rest",
"provider_route_id": null,
"pharmacy_order_uid": "po-abc123",
"pharmacy_order_name": "#1001",
"pharmacy_order_created_at": 1711899000,
"routing_created_at": null
},
{
"status": "projected",
"amount": 300,
"currency": "EUR",
"component_type": "item_markup",
"routing_description": "Medication X 100mg markup",
"provider_route_id": null,
"pharmacy_order_uid": "po-abc123",
"pharmacy_order_name": "#1001",
"pharmacy_order_created_at": 1711899000,
"routing_created_at": null
},
{
"status": "projected",
"amount": 499,
"currency": "EUR",
"component_type": "shipping",
"routing_description": "Standard Shipping",
"provider_route_id": null,
"pharmacy_order_uid": "po-abc123",
"pharmacy_order_name": "#1001",
"pharmacy_order_created_at": 1711899000,
"routing_created_at": null
}
],
"patient_data": {
"uid": "pat-123",
"display_name": "Max Mustermann",
"email": "max@example.com",
"date_of_birth": "15.06.1990",
"phone_number": "+49 170 1234567"
},
"doctor_data": {
"uid": "doc-456",
"display_name": "Dr. Schmidt"
},
"prescription_file": {
"filename": "prescription_001.pdf",
"content_base64": "JVBERi0xLjQK..."
},
"prepaid": 1
}
}
Field Reference
| Field | Type | Description |
|---|---|---|
data.uid | string | Pharmacy order UID |
data.status | string | Current order status |
data.name | string or null | Human-readable order name (e.g. #1001) |
data.data | object | Custom data attached to the order |
data.external_status | string | External status identifier |
data.created_at | integer | Unix timestamp of creation |
data.updated_at | integer | Unix timestamp of last update |
data.deleted_at | integer or null | Unix timestamp of soft-deletion, or null |
data.pharmacy | object | Pharmacy summary with uid and display_name |
data.order | object | Parent order with uid, delivery_address, and invoice_address |
data.order.shipping_costs_amount | integer or null | Shipping costs in cents. null when no shipping costs are available. |
data.order.shipping_costs_currency | string or null | ISO 4217 currency code for shipping costs, such as EUR. |
data.order.priority | integer | Priority hint for handling order sooner. Higher = more urgent. 0 means no special priority. |
data.delivery_type | object or null | Delivery type with uid, display_name, and identifier. Resolved from the connected shop’s fulfillment method (configured per shop), otherwise from the receiving pharmacy’s default delivery type. null when neither is set — do not assume a delivery type is always present. |
data.shop_shipping_methods | array | Shop shipping methods attached to the connected shop order. Empty array when the order has no shop shipping methods. |
data.shop_shipping_methods[].uid | string | Shop shipping method UID |
data.shop_shipping_methods[].display_name | string | Shop shipping method display name as configured on the shop |
data.shop_shipping_methods[].external_id | string or null | Identifier of the shipping method on the connected shop (e.g. the Shopify shipping line code) |
data.shop_shipping_methods[].pharmacy_mapping | object or null | Per-pharmacy mapping configured in the RxScale pharmacy settings, or null when no mapping has been configured for the receiving pharmacy yet. Configure this in the pharmacy Settings → Shipping method mappings screen. |
data.shop_shipping_methods[].pharmacy_mapping.pharmacy_uid | string | UID of the receiving pharmacy this mapping applies to |
data.shop_shipping_methods[].pharmacy_mapping.shipping_method_identifier_for_pharmacy | string | Pharmacy-specific identifier the receiving pharmacy expects for this shipping method (e.g. DHL_STANDARD). Use this value when handing the order off to your downstream shipping/labelling system. |
data.order_items | array | Items in the order |
data.order_items[].sku | object | SKU info including pzn, product_uid, product_display_name, standard_selling_unit, unit, and product_handle |
data.order_items[].sku.standard_selling_unit | number or null | Standard selling unit for the SKU |
data.order_items[].sku.unit | string or null | Unit for the SKU, such as ml or g |
data.order_items[].pharmacy_sku | object or null | Pharmacy-specific SKU data with uid, external_id, price (cents), stock |
data.order_items[].total_paid_amount | integer or null | Amount the patient paid for this line item, in cents (gross). null when no payment information is available. |
data.payouts | array | Payout components for this pharmacy order where the current pharmacy is the receiver. Paid physical-prescription orders include projected previews based on current values and routing configuration. Completed orders include routed payouts once a persisted split-payment route exists. |
data.payouts[].status | string | projected for an indicative preview, or routed for a persisted split-payment route created after pharmacy order completion. |
data.payouts[].amount | integer | Payout amount in cents. |
data.payouts[].currency | string | ISO 4217 currency code, such as EUR. |
data.payouts[].component_type | string | Payout component. Possible values are item_rest, item_markup, and shipping. |
data.payouts[].routing_description | string or null | Human-readable description of the routed or projected component. |
data.payouts[].provider_route_id | string or null | Payment provider route identifier. Populated for routed payouts when the provider returned an identifier, and null for projected payouts. |
data.payouts[].pharmacy_order_uid | string | UID of the related pharmacy order. |
data.payouts[].pharmacy_order_name | string or null | Human-readable pharmacy order name. |
data.payouts[].pharmacy_order_created_at | integer | Unix timestamp when the pharmacy order was created. |
data.payouts[].routing_created_at | integer or null | Unix timestamp when the split-payment route was created. null for projected payouts. |
data.patient_data | object or null | Patient info with uid, display_name, email, date_of_birth, phone_number |
data.doctor_data | object or null | Doctor who signed the prescription, with uid and display_name |
data.prescription_file | object or null | Signed prescription PDF with filename and content_base64 |
data.prepaid | integer | 1 if the order has a physical (prepaid) prescription, 0 otherwise |
Actual payment routing happens only when the pharmacy order is completed.
projected payouts in webhook payloads are indicative, only shown for paid physical-prescription orders, and can change before completion. routed payout values are only populated after completion and routing exists.pharmacy_order_updated
Sent when an existing pharmacy order’s status changes. The payload structure is identical topharmacy_order_created. The status field reflects the new status.
Payload Example
{
"event_type": "pharmacy_order_updated",
"timestamp": 1711910000,
"payload_version": "1",
"data": {
"uid": "po-abc123",
"status": "in-progress",
"name": "#1001",
"data": {},
"external_status": "IN_PROGRESS",
"created_at": 1711899000,
"updated_at": 1711910000,
"deleted_at": null,
"pharmacy": {
"uid": "ph-xyz",
"display_name": "City Pharmacy"
},
"order": {
"uid": "ord-123",
"delivery_address": {
"first_name": "Max",
"last_name": "Mustermann",
"street": "Hauptstr.",
"house_number": "1",
"zip_code": "10115",
"city": "Berlin",
"country": "Germany",
"additional_address": null,
"province": null
},
"invoice_address": {
"first_name": "Max",
"last_name": "Mustermann",
"street": "Hauptstr.",
"house_number": "1",
"zip_code": "10115",
"city": "Berlin",
"country": "Germany",
"additional_address": null,
"province": null
},
"shipping_costs_amount": 499,
"shipping_costs_currency": "EUR",
"priority": 5
},
"delivery_type": {
"uid": "dt-001",
"display_name": "Standard Shipping",
"identifier": "standard"
},
"shop_shipping_methods": [
{
"uid": "ssm-001",
"display_name": "DHL Standard",
"external_id": "shopify-standard",
"pharmacy_mapping": {
"pharmacy_uid": "ph-xyz",
"shipping_method_identifier_for_pharmacy": "DHL_STANDARD"
}
}
],
"order_items": [
{
"uid": "oi-789",
"amount": 1,
"sku": {
"uid": "sku-456",
"display_name": "Medication X 100mg",
"pzn": "12345678",
"product_uid": "prod-789",
"product_display_name": "Medication X",
"standard_selling_unit": 1.0,
"unit": "ml",
"product_handle": "medication-x"
},
"pharmacy_sku": {
"uid": "psku-456",
"external_id": "EXT-001",
"price": 1299,
"stock": 50
},
"total_paid_amount": 1299
}
],
"payouts": [
{
"status": "projected",
"amount": 999,
"currency": "EUR",
"component_type": "item_rest",
"routing_description": "Medication X 100mg item rest",
"provider_route_id": null,
"pharmacy_order_uid": "po-abc123",
"pharmacy_order_name": "#1001",
"pharmacy_order_created_at": 1711899000,
"routing_created_at": null
},
{
"status": "projected",
"amount": 300,
"currency": "EUR",
"component_type": "item_markup",
"routing_description": "Medication X 100mg markup",
"provider_route_id": null,
"pharmacy_order_uid": "po-abc123",
"pharmacy_order_name": "#1001",
"pharmacy_order_created_at": 1711899000,
"routing_created_at": null
},
{
"status": "projected",
"amount": 499,
"currency": "EUR",
"component_type": "shipping",
"routing_description": "Standard Shipping",
"provider_route_id": null,
"pharmacy_order_uid": "po-abc123",
"pharmacy_order_name": "#1001",
"pharmacy_order_created_at": 1711899000,
"routing_created_at": null
}
],
"patient_data": {
"uid": "pat-123",
"display_name": "Max Mustermann",
"email": "max@example.com",
"date_of_birth": "15.06.1990",
"phone_number": "+49 170 1234567"
},
"doctor_data": {
"uid": "doc-456",
"display_name": "Dr. Schmidt"
},
"prescription_file": {
"filename": "prescription_001.pdf",
"content_base64": "JVBERi0xLjQK..."
},
"prepaid": 1
}
}
Organisation-Level Webhooks
When the webhook subscription was created via the Management API (organisation-level), order events include additional data:- The
skuobjects insideorder_itemsandfulfillment.itemsare enriched with Shopify identifiers (shop_variation_id,shop_product_external_id). - A
fulfillmentobject is added with fulfillment order details.
{
"event_type": "pharmacy_order_updated",
"timestamp": 1711910000,
"payload_version": "1",
"data": {
"uid": "po-abc123",
"status": "in-progress",
"...": "... same fields as above ...",
"order_items": [
{
"uid": "oi-789",
"amount": 1,
"sku": {
"uid": "sku-456",
"display_name": "Medication X 100mg",
"pzn": "12345678",
"product_uid": "prod-789",
"product_display_name": "Medication X",
"standard_selling_unit": 1.0,
"unit": "ml",
"product_handle": "medication-x",
"shop_variation_id": "48372910234",
"shop_product_external_id": "93847261045"
},
"pharmacy_sku": {
"uid": "psku-456",
"external_id": "EXT-001",
"price": 1299,
"stock": 50
},
"total_paid_amount": 1299
}
],
"fulfillment": {
"uid": "fo-abc123",
"external_id": "EXT-FO-001",
"items": [
{
"uid": "foi-001",
"amount": 1,
"status": "init",
"external_id": "EXT-FOI-001",
"order_item": {
"uid": "oi-789",
"amount": 1,
"sku": {
"uid": "sku-456",
"display_name": "Medication X 100mg",
"pzn": "12345678",
"product_uid": "prod-789",
"product_display_name": "Medication X",
"standard_selling_unit": 1.0,
"unit": "ml",
"product_handle": "medication-x",
"shop_variation_id": "48372910234",
"shop_product_external_id": "93847261045"
}
}
}
],
"order": {
"uid": "ord-123",
"shop_order": {
"uid": "so-456",
"external_id": "SHOP-789",
"shop_identifier": "my-shopify-store"
}
}
}
}
}
| Field | Type | Description |
|---|---|---|
data.order_items[].sku.shop_variation_id | string or null | Shopify variant ID |
data.order_items[].sku.shop_product_external_id | string or null | Shopify product ID |
data.fulfillment.uid | string | Fulfillment order UID |
data.fulfillment.external_id | string or null | External identifier for the fulfillment order |
data.fulfillment.items[].order_item.sku.shop_variation_id | string or null | Shopify variant ID |
data.fulfillment.items[].order_item.sku.shop_product_external_id | string or null | Shopify product ID |
data.fulfillment.order.uid | string | Parent order UID |
data.fulfillment.order.shop_order.uid | string | Shop order UID |
data.fulfillment.order.shop_order.external_id | string or null | External shop order identifier |
data.fulfillment.order.shop_order.shop_identifier | string | Shop identifier |
The
fulfillment field and the Shopify identifiers (shop_variation_id, shop_product_external_id) inside sku objects are only present in organisation-level webhook deliveries. Pharmacy-level webhooks do not include these fields.pharmacy_sku_stock_updated
Sent when a pharmacy SKU’s stock level changes. This includes:- Direct stock updates via the Pharmacy API (
PATCH /v1/.../pharmacy_skus/{uid}/stockor inventory endpoints). - Automatic stock reduction when a pharmacy order is completed. This fires for both manual completion (via the pharmacy UI / API) and automatic completion when RxScale detects the order has reached a shipped or completed state via its status-check integration with the pharmacy’s backend. One event is emitted per pharmacy SKU on the completed order.
Payload Example
{
"event_type": "pharmacy_sku_stock_updated",
"timestamp": 1711900000,
"payload_version": "1",
"data": {
"uid": "psku-abc123",
"pharmacy_uid": "ph-xyz",
"sku_uid": "sku-456",
"external_id": "EXT-001",
"price": 1299,
"stock": 45,
"reserved_amount": 7,
"markup": 0,
"priority": 0,
"type": "default",
"created_at": 1711800000,
"updated_at": 1711900000,
"deleted_at": null,
"sku": {
"uid": "sku-456",
"display_name": "Medication X 100mg",
"pzn": "12345678",
"product_uid": "prod-789",
"product_display_name": "Medication X",
"standard_selling_unit": 1.0,
"unit": "ml",
"product_handle": "medication-x"
}
}
}
Field Reference
| Field | Type | Description |
|---|---|---|
data.uid | string | Pharmacy SKU UID |
data.pharmacy_uid | string | Pharmacy UID |
data.sku_uid | string | SKU UID |
data.external_id | string or null | External identifier in your own system |
data.price | integer | Price in cents |
data.stock | integer | Current stock level |
data.reserved_amount | integer | Units reserved against this SKU — sum of order item amounts across all in-flight pharmacy orders (i.e. orders not yet completed or cancelled). Useful to derive available stock as stock - reserved_amount. |
data.markup | integer | Markup value |
data.priority | integer | Priority level |
data.type | string | Pharmacy SKU type |
data.created_at | integer | Unix timestamp of creation |
data.updated_at | integer | Unix timestamp of last update |
data.deleted_at | integer or null | Unix timestamp of soft-deletion, or null |
data.sku | object | Nested SKU and product information |
data.sku.uid | string | SKU UID |
data.sku.display_name | string | SKU display name |
data.sku.pzn | string | Pharmazentralnummer (PZN) |
data.sku.product_uid | string | Parent product UID |
data.sku.product_display_name | string or null | Display name of the parent product |
data.sku.standard_selling_unit | number or null | Standard selling unit for the SKU |
data.sku.unit | string or null | Unit for the SKU, such as ml or g |
data.sku.product_handle | string or null | URL handle/slug of the parent product |
Organisation-Level Webhooks
When the webhook subscription was created via the Management API (organisation-level), stock events include additional data:- The
skuobject is enriched with Shopify identifiers (shop_variation_id,shop_product_external_id). - A
shop_identifierfield is added at thedatalevel.
{
"event_type": "pharmacy_sku_stock_updated",
"timestamp": 1711900000,
"payload_version": "1",
"data": {
"uid": "psku-abc123",
"pharmacy_uid": "ph-xyz",
"sku_uid": "sku-456",
"external_id": "EXT-001",
"price": 1299,
"stock": 45,
"reserved_amount": 7,
"markup": 0,
"priority": 0,
"type": "default",
"created_at": 1711800000,
"updated_at": 1711900000,
"deleted_at": null,
"shop_identifier": "my-shopify-store",
"sku": {
"uid": "sku-456",
"display_name": "Medication X 100mg",
"pzn": "12345678",
"product_uid": "prod-789",
"product_display_name": "Medication X",
"standard_selling_unit": 1.0,
"unit": "ml",
"product_handle": "medication-x",
"shop_variation_id": "48372910234",
"shop_product_external_id": "93847261045"
}
}
}
| Field | Type | Description |
|---|---|---|
data.shop_identifier | string or null | Shop identifier |
data.sku.shop_variation_id | string or null | Shopify variant ID |
data.sku.shop_product_external_id | string or null | Shopify product ID |
The
shop_identifier field and the Shopify identifiers (shop_variation_id, shop_product_external_id) inside the sku object are only present in organisation-level webhook deliveries. Pharmacy-level webhooks do not include these fields.appointment_reminder_due
Sent when a configured appointment reminder becomes due. This event is delivered to organisation-level webhook subscriptions only.Reminders can also carry direct action links for the patient (join, reschedule, cancel) via RxScale’s own email/SMS content. The
rebook_allowed and cancel_allowed fields below tell you whether those actions are currently available — they are only ever true when recipient_role is patient.Payload Example
{
"event_type": "appointment_reminder_due",
"timestamp": 1893452400,
"payload_version": "1",
"data": {
"appointment_uid": "appt-e2e-123",
"organisation_uid": "org-abc123",
"shop_uid": "shop-e2e-1",
"appointment_type_reminder_uid": "reminder-e2e-1",
"recipient_role": "doctor",
"recipient_email": "doctor@example.com",
"recipient_phone_number": "+491701234567",
"recipient_display_name": "Dr. Grace Hopper",
"patient_uid": "patient-e2e-1",
"patient_display_name": "Ada Lovelace",
"doctor_uid": "doctor-e2e-1",
"doctor_display_name": "Dr. Grace Hopper",
"appointment_type_uid": "type-e2e-1",
"appointment_type_name": "Consultation",
"visit_reason": "Medication review before changing dosage",
"start_date": 1893456000,
"end_date": 1893457800,
"estimated_duration_minutes": 30,
"minutes_before": 60,
"rebook_allowed": false,
"cancel_allowed": false,
"send_email": true,
"send_sms": false
}
}
Field Reference
| Field | Type | Description |
|---|---|---|
data.appointment_uid | string | Scheduled appointment UID |
data.organisation_uid | string | UID of the organisation the appointment belongs to |
data.shop_uid | string or null | Shop UID associated with the patient, if available |
data.appointment_type_reminder_uid | string | Reminder rule UID |
data.recipient_role | string | Recipient role: patient, doctor, or admin |
data.recipient_email | string or null | Resolved recipient email, if available |
data.recipient_phone_number | string or null | Resolved recipient phone number, if available |
data.recipient_display_name | string or null | Resolved recipient display name |
data.patient_uid | string | Patient profile UID |
data.patient_display_name | string | Patient display name |
data.doctor_uid | string | Doctor UID |
data.doctor_display_name | string | Doctor display name |
data.appointment_type_uid | string or null | Appointment type UID |
data.appointment_type_name | string or null | Appointment type name |
data.visit_reason | string or null | Optional reason, supplied when the hold was created or updated at confirm |
data.start_date | integer | Appointment start time (Unix timestamp) |
data.end_date | integer or null | Appointment end time (Unix timestamp), if known |
data.estimated_duration_minutes | integer or null | The appointment’s estimated duration, in minutes |
data.minutes_before | integer | Reminder offset in minutes before the appointment |
data.rebook_allowed | boolean | Whether the patient can currently reschedule via the reminder’s action link. Only ever true when recipient_role is patient, the appointment type allows patient rebooking, and timing rules (e.g. minimum notice) are currently met |
data.cancel_allowed | boolean | Whether the patient can currently cancel via the reminder’s action link. Only ever true when recipient_role is patient and timing rules (e.g. minimum notice) are currently met |
data.send_email | boolean | Whether RxScale’s notification handler should send email for this reminder |
data.send_sms | boolean | Whether RxScale’s notification handler should send SMS for this reminder |
patient_doctor_meeting_updated
Sent when a patient-doctor meeting changes lifecycle state. This event is delivered to organisation-level webhook subscriptions only (registered via the Management API). Possiblechange values:
| Value | When emitted |
|---|---|
held | A scheduled appointment was held (the meeting window opened) |
confirmed | A scheduled appointment was confirmed |
expired | A scheduled appointment expired without being joined |
cancelled | A meeting was cancelled |
rebooked | A meeting was rebooked (a new meeting replaced this one) |
completed | A meeting was completed — an on-demand meeting ended, or a doctor recorded a confirmed appointment as completed |
no_show | A doctor recorded a confirmed appointment as a no-show (the patient did not attend) |
Use
change as the authoritative indicator of what happened. status reflects the meeting’s current database status and is null for on-demand meetings.Payload Example
{
"event_type": "patient_doctor_meeting_updated",
"timestamp": 1893456000,
"payload_version": "1",
"data": {
"organisation_uid": "org-abc123",
"meeting_uid": "m-e2e-1",
"change": "confirmed",
"status": "confirmed",
"meeting_type": "consultation",
"meeting_format": "digital",
"start_date": 1893456000,
"end_date": 1893456900,
"estimated_duration_minutes": 15,
"confirmed_at": 1893450000,
"cancelled_at": null,
"cancellation_reason": null,
"visit_reason": "Medication review before changing dosage",
"expires_at": null,
"previous_meeting_uid": null,
"appointment_type_uid": "at-1",
"doctor_uid": "doc-1",
"patient_profile_uid": "pat-1"
}
}
Field Reference
| Field | Type | Description |
|---|---|---|
data.organisation_uid | string | UID of the organisation the meeting belongs to |
data.meeting_uid | string | Unique identifier for the meeting |
data.change | string | The lifecycle transition that triggered this event — see the table above |
data.status | string or null | Current status of the meeting. null for on-demand meetings; use change for logic instead |
data.meeting_type | string | Type of meeting (e.g. consultation) |
data.meeting_format | string | Format of the meeting (e.g. digital) |
data.start_date | integer or null | Unix timestamp of the scheduled start (scheduled appointments only) |
data.end_date | integer or null | Unix timestamp of the planned end for scheduled appointments. This is the originally scheduled end time, not the actual end |
data.estimated_duration_minutes | integer or null | Estimated duration in minutes |
data.confirmed_at | integer or null | Unix timestamp of when the meeting was confirmed, or null |
data.cancelled_at | integer or null | Unix timestamp of cancellation, or null |
data.cancellation_reason | string or null | Reason for cancellation, or null |
data.visit_reason | string or null | Optional reason, supplied when the hold was created or updated at confirm. May also appear in reminder content and synced calendar invite descriptions |
data.expires_at | integer or null | Unix timestamp after which the meeting link expires, or null |
data.previous_meeting_uid | string or null | UID of the meeting this one was rebooked from, or null. Set when change is rebooked |
data.appointment_type_uid | string or null | UID of the appointment type (scheduled appointments only) |
data.doctor_uid | string or null | UID of the assigned doctor |
data.patient_profile_uid | string | UID of the patient profile. This is the only patient identifier in the payload — no PII (name, date of birth, or contact details) is included |
Subscribing
Subscribe via the Management API to receive this event:curl -X POST "https://api.rxscale.com/v1/management/notification-subscriptions/" \
-H "X-API-Key: your-api-key-here" \
-H "Content-Type: application/json" \
-d '{
"notification_type": "patient_doctor_meeting_updated",
"target": "https://your-system.com/webhooks/rxscale"
}'
Delivery and Idempotency
Webhooks are delivered at least once. Your endpoint should treat deliveries as idempotent using the combination ofdata.meeting_uid and data.change as the unique key — retried deliveries will carry the same values.