API reference
Platform API (v1)
Server-to-server endpoints for pharmacy systems: read a certificate, mint seal batches, download labels, issue passports, decide orders against your release policy, and receive signed events. All /v1 requests are JSON and authenticate with an API key.
Base URL & conventions#
https://www.veritura.co
Authorization: Bearer vk_live_…for production,vk_test_…for sandbox records that are never patient-visible: see authentication.- Field names accept
snake_case(canonical, shown here) andcamelCasealiases. - Every endpoint is rate-limited per key, by plan: 600 requests a minute on a paid plan and 1,200 with supported API automation (Operations); the free buyer read API allows 300 a minute per workspace. Refusals are plain sentences with machine codes: see errors & rate limits.
- Keys that write (checks, decisions, Passports, Seals) and signed webhooks are on the Operations plan; a read-only key for the read API is free on any plan. A key lasts 90 days unless you set another expiry (up to 366 days), and carries only the permissions you chose.
Endpoints#
| Endpoint | Purpose | |
|---|---|---|
| POST | /v1/check | Read one laboratory document and file the report, creating or updating the lot it identifies. |
| POST | /v1/seal-batches | Mint unit serials for a logged lot. |
| GET | /v1/seal-batches/<id>/labels | Download a batch's labels as ZPL, thermal PDF, or an Avery sheet. |
| POST | /v1/passports | Issue the Evidence Passport, the document-side record for one order. |
| POST | /v1/cleargate | One release-policy decision for one order: allow, review or hold, each reason named, signed and hash-chained. Send lot_id, or supplier with optional product and lot; order_id carries your reference. |
| POST | /v1/cleargate-batch | A purchase order screened line by line (po_ref, lines: [{supplier, product, lot}]); one signed decision per line, and the worst line governs. |
| GET | /v1/cleargate/decisions/<id>.pdf | One signed decision as the determination PDF the workspace downloads, for the batch record. Your own account's decisions only. |
| GET | /v1/cleargate/log.csv | Every decision in your account's chain, oldest first, one row each with its signature and hash links, so the chain can be re-verified outside Veritura. Paged by offset and limit (up to 5,000 rows). |
| POST | /v1/eligibility | Whether a substance is eligible to compound for a facility type against FDA's current lists (substance, facility_type): allow, review or hold, signed. |
| GET | /v1/network/directory · /v1/network/source | The published verified-source directory, and one source by id. Read-only. |
| POST | /v1/network/route | A ship-to-state routing decision against the eligibility rules. |
| GET | /v1/pharmacies, /v1/suppliers, /v1/lookups, /v1/watches, /v1/exposure | The read API for published pharmacy and supplier files, documented on its own page. |
| GET | /api/verify-unit-public | Public: resolve a unit serial to its record. |
| GET | /api/customer-passport/<share_id> | Public: resolve a passport share link to the released record. |
Workspace endpoints used in the guides#
These are operator-facing (workspace session, same-origin) and appear in the integration guide; they are listed for completeness. A server integration should use the /v1 endpoints above.
| Endpoint | Purpose |
|---|---|
POST /api/account-profile | Declare the pharmacy's own identity for self-dispensed records: dispenserLicenseState (two letters), dispenserLicenseNumber. 503A/503B facilities only. |
POST /api/lots/<id>/pharmacist-release | The responsible pharmacist releases a pending lot of the pharmacy's own preparation, with a required reason; recorded with name and licence. Refused for flagged, recalled, held, or purchased-material lots. |
POST /api/seal-batch · GET /api/seal-batch-pdf | Workspace equivalents of the v1 seal endpoints. |
POST /api/evidence-passports · POST /api/evidence-passports/release | Workspace passport issuance and release. |
Webhooks#
Register an endpoint in the workspace (Settings, Developer) and choose its events. The signing secret is shown once, when you register it. A test event can be sent from the same place. The endpoint must be a public https address: plain HTTP, localhost, private, link-local and loopback addresses are refused when you register it, and the resolved address is checked again at every delivery. Redirects are not followed.
The seven events
| Event | Sent when |
|---|---|
passport.issued | A Passport is released, by any path: the lot page, the passport list, a watched folder, an order hook, order events, a staged batch release, a policy release, the order channel or /v1/passports. Once per Passport. A telehealth platform also receives it for a Passport issued on its own order, with its own order reference. |
lot.recall_hit | A recall case on one of your lots becomes active or gains a new assertion: an FDA enforcement record names the lot number (via: "lot_recall_net" or "account_sweep"), or a person declares a recall (via: "declared"). confirmation says whether a person has declared it (declared_by_a_person) or the match is waiting for a person (awaiting_a_person); firmCheck compares the recalling firm with the lot's supplier, maker and laboratory. A telehealth platform whose order's Passport came from the lot receives it too, with its order references. |
lot.held · lot.hold_lifted | A lot is held or released from a hold: a person's hold, a ClearGate hold (reason: "cleargate") or a recall (reason: "recall"). A dismissed recall sends lot.hold_lifted; a closed recall keeps the lot held and sends nothing. |
supplier.alert | The hourly sweep finds a confirmed or strong FDA enforcement match on a supplier, maker or laboratory you hold, or a laboratory answers a verification request. |
file.changed | A pharmacy or supplier file you watch changed at its weekly look-up. |
lot.conflict_hit | The same lot number appears with different stated values on another document on the network. Only the conflicting field is named, never another account. |
The delivery
POST <your endpoint>
Content-Type: application/json
X-Veritura-Event: lot.recall_hit
X-Veritura-Event-Id: evt_6f238e4c9082f14a99df00a2
X-Veritura-Signature: sha256=<hex HMAC-SHA256 of the raw body, keyed with your signing secret>
{ "id": "evt_6f238e4c9082f14a99df00a2", "event": "lot.recall_hit", "created": "2026-10-19T00:18:41.720Z", "attempt": 1,
"data": { "via": "lot_recall_net", "lots": [{ "lot": "TY9495", "lotId": "LOT-…", "product": "…", "supplier": "…", "recallNumber": "D-0877-2026" }],
"lotIds": ["LOT-…"], "source": "fda", "reference": "D-0877-2026", "confirmation": "awaiting_a_person", "caseVersion": 1 } }
Verify the signature over the raw body before parsing it. The event id is inside the signed body and in X-Veritura-Event-Id; a redelivery carries the same id and a higher attempt, so you can discard a repeat. A passport.issued body carries passportId, orderId (your reference), lotId (the lot's id), lotNumber (the batch number), product, environment, verifyUrl (absolute) and verifyPath.
Retries
A delivery is settled by a 2xx. A transport failure, a timeout (5 seconds), a 408, 425, 429 or 5xx is retried with exponential backoff and full jitter, starting at 30 seconds and doubling, for at most 6 attempts in all. Any other 4xx, and a redirect, is not retried. Every attempt is recorded, and the latest outcome is shown beside the endpoint in the workspace.