Developer Changelog
RxRelay API changes
Developer-facing changes to the RxRelay API, webhook events, documentation, and integration tooling.
2026-08-19
Prescription and shipping details in order responses
- Order item responses now include directions, allowing integrations to retrieve the stored prescription sig with GET/v1/orders/{orderId} when a pharmacy requests clarification.
- The additive field also appears in POST/v1/orders and POST/v1/orders/{orderId}/approval responses, plus standard order and order.tracking_updated webhook item payloads. No existing fields changed or were removed.
- Order responses, list summaries, and standard order and tracking webhooks now include shippingMethod, the effective normalized service stored after routing (Standard or Overnight). It may differ from the requested value when the pharmacy owns service selection: LifeFile is always Overnight, while Boothwyn's vendor-native service is configured separately and represented as Standard.
2026-08-12
Kaduceus and Boothwyn pharmacy notes
- POST/v1/orders now accepts optional items[].pharmacyNotes for Kaduceus/Pioneer and Boothwyn medications. RxRelay snapshots the note on the prescription line; Boothwyn receives it per prescription, while Pioneer receives it through the order-level notes field.
- Each note is limited to 500 characters. For Kaduceus submissions with multiple prescription lines, distinct nonblank notes are combined in item order and must also total 500 characters or fewer. Notes supplied for another pharmacy return 400 Bad Request rather than being silently discarded.
- Full order responses and order webhook item payloads now echo pharmacyNotes. This is an additive request and response change; no existing fields changed or were removed.
2026-08-11
Agent-assisted integration, reviews, and API updates
- The API documentation now provides official coding-agent skills for implementing a new RxRelay integration, reviewing an existing one, or updating it against the latest OpenAPI contract and changelog.
- All workflows retrieve the current public contract rather than relying on model memory, enforce safe sandbox/live credential handling, run relevant tests, and refresh human-readable and machine-readable RxRelay readiness reports.
- Review and update workflows begin read-only, report relevant releases and integration gaps, and request permission on a concrete file-by-file plan before editing. All skills prohibit putting secrets in chat and prohibit live order mutations.
- New integrations, reviews, and API updates focus on the concrete work required for valid, safe order submission. Optional performance and production hardening are reported separately; broader production certification runs only when explicitly requested.
- The integration skill now asks partners to choose Full, Standard, or Minimal scope. Full and Standard cover the broader clinic workflow across medications/products, pharmacies, prescribers, patients, addresses, orders, and status synchronization; organization-scoped features remain deferred by default.
- Rerunning a documentation prompt refreshes the installed skill from its canonical URL, and every RxRelay skill checks the current published procedure before acting so an older installed copy cannot silently use stale instructions.
- Skill install and reference URLs use the canonical www.rxrelay.ai host so direct-download installers do not depend on following the apex-domain redirect.
2026-08-07
Tracking on full order responses
- GET/v1/orders/{orderId} now returns trackingNumber and updatedAt at the top level, matching the order summaries returned by GET/v1/orders and GET/v1/patients/{patientId}/orders.
- trackingNumber is null until tracking is received. updatedAt uses the same lifecycle activity calculation as the list response, so clients can compare the summary and detail representations reliably.
- The shared full-order shape returned by POST/v1/orders and POST/v1/orders/{orderId}/approval, and included in standard order webhook payloads, gains the same additive fields. No existing fields changed or were removed.
2026-08-06
Required quantity for Boothwyn metoprolol
- Boothwyn SKU 13776 (Metoprolol Succinate 25mg ER) must be ordered with quantity 6 on POST/v1/orders. Any other quantity returns 400 Bad Request before the order is created.
- The RxRelay order and bulk-entry screens now default this product to quantity 6. The Boothwyn dispatch path enforces the rule again so queued orders and retries cannot bypass it.
- GET/v1/medications now includes nullable requiredQuantity. Partners should use a non-null value as the exact items[].quantity for that product. This is an additive response change; no existing fields changed or were removed.
2026-08-05
Tracking and update timestamps in order lists
- Order summaries returned by GET/v1/orders and GET/v1/patients/{patientId}/orders now include trackingNumber and updatedAt.
- trackingNumber is the latest tracking number for the order's pharmacy submission. It is null until tracking is received, then lets integrations display tracking without fetching every order individually.
- updatedAt is the latest partner-visible order activity. It advances for submission attempts, approval or cancellation, and vendor status or tracking events; it equals createdAt until the order changes.
- This is an additive response change — no existing fields changed or were removed. The hosted OpenAPI endpoint reflects the new fields when the updated API is deployed.
2026-08-01
Prescriber approval queue visibility
- Orders can now be staged inside the RxRelay app for a prescriber to approve before anything reaches a pharmacy. Orders created through this API are unaffected — they continue to dispatch immediately and are never queued.
- Order responses gained an approval object — status (Pending, Approved, or Rejected), submittedForApprovalAt, reviewedAt, and note. It appears on GET/v1/orders/{orderId}, POST/v1/orders, and the summaries returned by GET/v1/orders and GET/v1/patients/{patientId}/orders. It is null for every order that did not go through the queue.
- Aggregate order status can now be PendingApproval, meaning the order is waiting on a prescriber and has not been sent to a pharmacy. If you branch on status, treat it as not-yet-dispatched rather than an error. It is also accepted as a status filter on GET/v1/orders.
- Three webhook events were added: order.pending_approval, order.approved, and order.rejected. order.approved is distinct from order.sent — approved is the human decision, sent is the pharmacy hand-off that follows it. They use the same envelope and data.order nesting as existing order events.
- Existing webhook destinations are unchanged: each endpoint stores its own event subscription list, so no destination begins receiving these events until it explicitly subscribes.
- Creating an order now returns 400 when the resolved prescriber has no NPI on file. Every pharmacy payload requires one, so these orders previously failed later at dispatch instead of being rejected up front.
- Aside from the new status value, this is an additive change — no existing fields changed or were removed.
- Two-step ordering is now available through the API as well: send submitForApproval on POST/v1/orders to hold an order, then release it with POST/v1/orders/{orderId}/approval. approverUserId is required and must be a prescriber, owner, or clinic admin in that clinic; look ids and roles up with GET/v1/users. stagedByUserId is optional and attributes who prepared the order.
- Both are opt-in. Orders created without submitForApproval behave exactly as before.
2026-07-29
Prescriber returned on orders
- Order responses now include prescriber, the prescriber the order was written under — userId, firstName, lastName, and npi. Previously the prescriber could be set on an order but never read back, so a webhook receiver had no way to attribute an order without tracking it itself.
- prescriber appears on GET/v1/orders/{orderId} and POST/v1/orders, on the summaries returned by GET/v1/orders and GET/v1/patients/{patientId}/orders, and in the order.* and order.tracking_updated webhook payloads.
- The object is null when an order has no prescriber on record, and npi within it is nullable. prescriber.userId matches the userId returned by GET/v1/prescribers.
- This is an additive change — no existing fields changed or were removed.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-07-14
Patient email and phone required
- Creating a patient now requires email and phone in addition to firstName, lastName, and dateOfBirth. This applies to POST/v1/patients and to inline patient creation on POST/v1/orders — a request missing either returns 400 Bad Request.
- Email and phone are required to prescribe: the fulfilling pharmacy rejects a submission without them, so an order that would otherwise be created and then fail downstream is now rejected up front.
- POST/v1/orders returns 400 Bad Request when an order routes to a pharmacy that requires the patient's email and the patient has none on file. Creating a patient with these fields resolves it.
- A missing shipping address on POST/v1/orders now returns 400 Bad Request instead of a server error.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-07-11
Curated pharmacy medication names
- GET/v1/medications now uses a human-curated product label for Kaduceus and LifeFile products when an exact downstream-product override is configured, with the pharmacy's raw name as fallback.
- Curated labels are display-only. Ordering and pharmacy dispatch continue to use the original medication id and downstream product identifier.
- The RxRelay medication pickers treat a curated name as a complete label while continuing to render structured vial size separately.
2026-07-11
Optimal Balance package sizes and active catalog status
- GET/v1/medications now populates vialSize for mapped Optimal Balance injections and creams when LifeFile includes a trailing package volume in its catalog strength.
- Optimal Balance medication maps now support active/inactive status. Inactive products are excluded from catalogs and new orders while remaining available to already-created orders for dispatch and retry safety.
- The hosted OpenAPI endpoint reflects the updated LifeFile administration contract when the updated API is deployed.
2026-07-10
Medication vial sizes
- GET/v1/medications now returns vialSize, the fulfilling pharmacy's vial volume for injectable products when supplied by its catalog.
- vialSize is nullable because availability varies by pharmacy and product. Existing request and ordering behavior is unchanged.
- The hosted OpenAPI endpoint reflects this change when the updated API is deployed.
2026-07-09
Per-pharmacy medication catalogs
- GET/v1/pharmacies lists the distinct pharmacies your clinic can dispense from, each with a stable, opaque id and display name.
- GET/v1/medications now accepts an optional pharmacyId query parameter — pass an id from GET/v1/pharmacies to retrieve just that pharmacy's formulary. Omit it for the clinic's full unified catalog, exactly as before.
- A malformed pharmacyId returns 400; a well-formed id your clinic isn't entitled to returns an empty array. No existing response fields changed.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-07-08
Register prescribers and users via the API
- POST/v1/users creates or updates a user in your clinic and assigns clinic roles — register prescribers programmatically instead of the onboarding spreadsheet. The clinic comes from your API key, so no clinic reference is needed.
- A prescriber must include an npi; once registered it can be referenced on orders by prescriberNpi. The call is idempotent per email — an existing email links to that user and merges roles.
- GET/v1/users lists your clinic's users with roles and NPI, so you can check whether a prescriber is already registered before ordering.
- GET/v1/clinic returns your clinic's own record — including its RxRelay clinic id and sandbox flag — for clinic-scoped keys.
- Organizations gain GET/v1/clinics/{clinicRef}/users to list a clinic's users. On the org user endpoints, {clinicRef} is now the RxRelay clinic id (a UUID); the externalClinicId alias is no longer accepted there.
- platform_admin can no longer be assigned through the API; assignable roles are prescriber, clinic_admin, staff, and owner.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-07-08
Structured medication ingredients
- GET/v1/medications now returns an ingredients array for each medication — the structured per-active composition (name, concentration, unit) when the fulfilling pharmacy provides it.
- The array is empty when no structured data is available; strength stays the flat summary. For a multi-active blend, ingredients describes what a single strength value cannot.
- ingredients is informational for display and selection — ordering is unchanged and still references a medication by id.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-06-29
Generic order metadata
- POST/v1/orders now accepts optional metadata: a generic key/value object for display and audit context.
- Metadata is stored with the order, returned by order read/list APIs, shown on the RxRelay order detail page, and included in order webhooks.
- Metadata is not used for auth, routing, billing, or fulfillment logic. Values must be string, number, boolean, or null; nested objects and arrays are rejected.
- Limits are 20 keys, 64 characters per key, and 512 characters per value.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-06-27
Expanded medication response
- GET/v1/medications now returns strength, form, pharmacyName, and pharmacySku for each medication, in addition to id and name.
- pharmacySku is the fulfilling pharmacy's own product identifier (the downstream SKU) for that medication — useful for reconciling RxRelay's catalog against a pharmacy's price list.
- All four fields are populated when the fulfilling pharmacy provides them and are null otherwise.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-06-27
Patient and order management endpoints
- Added GET/v1/patients to list and search patients by name, email, phone, date of birth, or externalPatientId, with limit/offset pagination and a total count.
- Added GET/v1/patients/{patientId} to fetch a single patient and its active addresses.
- Added POST/v1/patients to create or resolve a patient outside of an order (by externalPatientId or email), with an optional default address.
- Added PATCH/v1/patients/{patientId} to update patient demographics. Remapping externalPatientId to a patient already mapped elsewhere returns 409 Conflict.
- Added GET/v1/orders to list and search orders by status, patient, externalOrderId, and date range, plus GET/v1/patients/{patientId}/orders for a single patient's orders. Both are paginated, newest first.
- Added GET/v1/patients/{patientId}/addresses/{addressId}, DELETE on the same path to deactivate an address (promoting a new default if needed), and POST.../default to set an existing address as the default.
- Reads work with any valid key; writes (POST/PATCH/DELETE) require a read_write key. Organization keys scope these via clinicId or externalClinicId.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-06-23
Patient address IDs for partner orders
- POST/v1/orders now accepts exactly one of shippingAddressId or shippingAddress. Existing shippingAddress behavior is preserved.
- When a full shippingAddress exactly matches an existing patient address, RxRelay reuses that address instead of creating a duplicate.
- Added GET/v1/patients/{patientId}/addresses and POST/v1/patients/{patientId}/addresses so partners can retrieve, upsert, store, and reuse RxRelay address IDs.
- Patient address cards in the RxRelay app now show a copyable Address ID.
- The hosted OpenAPI endpoint reflects these changes when the updated API is deployed.
2026-06-23
Webhook delivery decoupled from order submission
- Outbound partner webhooks are now delivered asynchronously through the RxRelay worker instead of being attempted on the POST/v1/orders request path.
- POST/v1/orders response bodies and webhook payloads are unchanged; partners should continue treating webhooks as asynchronous status events.
- Webhook delivery remains single-attempt by default. Failed deliveries are recorded in the webhook event log and can be manually replayed from Settings / API.
- The hosted OpenAPI endpoint continues to document POST/v1/orders as returning 201 Created.
2026-06-19
Organizations: order on behalf of clinics and provision via API
- Added organization-scoped API keys. An organization owns many clinics and is issued one key instead of one key per clinic.
- POST/v1/orders now accepts clinicId or externalClinicId. Organization keys must name the target clinic on each order; clinic-scoped keys are unchanged.
- GET/v1/medications and GET/v1/prescribers accept a clinicId or externalClinicId query parameter to scope results for organization keys.
- Added GET/v1/clinics to list the clinics under an organization.
- Added POST/v1/clinics and POST/v1/clinics/{clinicRef}/users to provision clinics and their users — available to organization keys once RxRelay enables provisioning. Clinic creation is idempotent on externalClinicId.
2026-06-12
Required shipping address on orders
- POST/v1/orders now requires a shippingAddress object (address1, address2, city, state, zip). Orders without a valid shipping address are rejected with 400.
- The supplied address is saved as the patient's default address and sent to the fulfilling pharmacy.
2026-06-06
Developer platform foundation
- Added clinic-scoped RxRelay API documentation under RxRelay Developers.
- Added public OpenAPI endpoint at https://api.rxrelay.ai/openapi/v1.json.
- Added request IDs, documented rate limits, idempotency behavior, and Problem Details errors.
- Added webhook delivery event log with manual replay for failed deliveries.
- Added order.tracking_updated webhook event for upstream tracking updates.