REST API & webhooks
Authenticate to the Curably Platform, call org-scoped endpoints, subscribe to lifecycle events, and verify signed webhook deliveries.
Last updated June 2026
Base URL
Production and sandbox base URLs are issued during onboarding. All requests must use HTTPS with TLS 1.2 or higher. Paths are rooted at /api/... relative to your assigned host.
Authentication
Curably supports two authentication modes:
- Bearer token (staff context) — Supabase session JWT for provider, pharmacy, HMO, and admin workspace calls. Obtained after staff sign-in with MFA where required.
- Organization API keys — Server-to-server tokens with least-privilege scopes per module (records, verifications, webhooks). Managed under Admin → Integrations.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Org isolation
org_id the caller is authorized for. Cross-org access returns 403.Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Bearer token or API key |
| Content-Type | POST/PUT | application/json |
| Idempotency-Key | Recommended | Client-generated UUID for safe retries on POST |
| X-Cura-Signature | Pharmacy HMAC | sha256 HMAC of raw body (see Pharmacy API) |
Core endpoints
/api/consentsList consent grants for a beneficiary. Query: subject_cura_id, org_id, include_revoked.
/api/consentsRequest scoped access for a beneficiary. Use auto_approve when consent is captured on-site at kiosk or intake.
/api/consents/revokeRevoke active consent; halts outbound record sync immediately.
/api/recordsFetch medical records for a subject under active consent scopes.
/api/records/pushPush a record to EHR, payer, pharmacy, or other org-scoped targets under active consent.
/api/verificationsList identity verification events for an organization.
/api/verificationsRecord a verification outcome (verified, flagged, rejected).
/api/auditFetch org-scoped audit log entries. Query: org_id, limit.
/api/orgs/webhooksList registered webhook endpoints for an organization (admin + MFA).
/api/orgs/webhooksRegister a webhook URL; returns a signing secret.
Pharmacy-specific endpoints are documented in Pharmacy API. EHR sync endpoints are covered in EHR integration.
Webhooks
Register webhook URLs via POST /api/orgs/webhooks with { org_id, url }. Curably generates a per-endpoint secret used to sign deliveries.
{
"event": "consent.created",
"org_id": "uuid",
"patient_id": "uuid",
"subject_cura_id": "CURA-XXXX",
"scopes": ["records.read", "medications.read"],
"timestamp": "2026-06-10T14:32:00Z"
}Supported events:
consent.created— beneficiary granted scoped accessconsent.revoked— access withdrawnvisit.started— encounter opened at facilityvisit.closed— encounter closed with billing contextverification.flagged— identity or fraud signal raisedwebhook.created— audit event on endpoint registration
Failed deliveries retry with exponential backoff (1s, 2s, 4s, 8s — max 5 attempts). Your endpoint should return 2xx within 10 seconds.
Signature verification
Webhook deliveries include X-Cura-Signature: sha256=<hex> computed as HMAC-SHA256 of the raw request body using your endpoint secret.
const crypto = require("crypto");
function verifyWebhook(req, secret) {
const sig = req.headers["x-cura-signature"] || "";
const raw = req.rawBody || JSON.stringify(req.body);
const h = crypto
.createHmac("sha256", secret)
.update(raw, "utf8")
.digest("hex");
return sig === "sha256=" + h;
}Rate limits & retries
- Use
Idempotency-Keyon POST requests to prevent duplicate writes during retries - On
429 Too Many Requests, honor theRetry-Afterheader - Default sandbox limit: 120 requests/minute per org; production limits scale with contract tier
Error handling
| Status | Meaning | Action |
|---|---|---|
| 400 | Validation error | Fix request body or query params |
| 401 | Missing/invalid auth | Refresh token or check API key |
| 403 | Forbidden | Verify org membership and consent scopes |
| 404 | Resource not found | Check IDs and patient resolution |
| 429 | Rate limited | Backoff per Retry-After |
| 500 | Server error | Retry with jitter; contact support if persistent |