Oryen®Back to overview
Developers

Organization API integration guide.

For organizations connecting their own software to Oryen Health. Covers how patients are identified across both systems, what is safe to retry, and how device assignment governs whether readings arrive.

API reference

The full endpoint reference, with request and response shapes, is published as an OpenAPI document you can try requests against: Organization API reference.

Read this guide first. The reference describes each endpoint; this explains how they fit together.

For an organization integrating Oryen Health with its own software.

The OpenAPI reference at /api/docs/partner lists every endpoint and field. This document covers what the reference cannot: how patients are identified across the two systems, what is safe to retry, and which failures mean "stop" rather than "try again".


The model in one paragraph

Oryen holds the monitoring record. You create a patient through this API using your own identifier, attach a device to them, and read back readings and alerts — each one carrying that same identifier. You never store an Oryen UUID, and you never keep a mapping table between your patients and ours. The clinical work (NEWS2 scoring, alert thresholds, reminders, escalation) happens in Oryen.

Access

API access is enabled per organization by Oryen, not self-service. Once enabled, an administrator in your organization creates an API client and receives a key once — it is not retrievable afterwards, only rotatable.

Authenticate with either:

x-oryen-api-key: oh_live_<prefix>_<secret>
Authorization: Bearer oh_live_<prefix>_<secret>

The key determines the organization. There is no organization field in any request body, and sending one is rejected.

Scopes

Scope Grants
patients:read List and fetch patients
readings:read Readings, per patient or latest across the caseload
alerts:read Open and historic alerts
devices:read Devices and current assignments
patients:write Create and update patients
devices:write Assign and end device assignments

Write scopes are never granted by default. Request only what the integration uses: a dashboard that reads should not hold a key that can create patients.

Rate limits

Limit
All requests 120 per minute per key
Write requests 30 per minute per key, in addition to the above

Exceeding either returns 429. Writes count against both, so 30 writes plus 90 reads is the ceiling in a minute. If a migration needs more, talk to us rather than retrying into the limit.


Identifying patients

Two identifiers matter, and they do different jobs.

externalRef — yours. Whatever your system calls the patient: an MRN, an EHR key, a local id. Opaque to Oryen; we store it and hand it back. It is unique within your organization, and it is how you address a patient in every request after creation.

nhsNumber — theirs. Optional but strongly recommended. Validated on the check digit, not merely on length, so a transposed digit is rejected rather than silently naming a different person. Unique within your organization.

You address patients by externalRef throughout:

PATCH /api/v1/organization/patients/EHR-00042

Readings and alerts come back carrying patientExternalRef, so a reading can be filed without a lookup.

NHS numbers appear on the patients endpoint only, behind patients:read. They are deliberately not embedded in readings or alerts: a key scoped to readings alone should not receive them.


Enrolling a patient

POST /api/v1/organization/patients
x-oryen-api-key: oh_live_…
Content-Type: application/json

{
  "externalRef": "EHR-00042",
  "fullName": "Jane Doe",
  "dateOfBirth": "1958-04-11",
  "gender": "female",
  "nhsNumber": "9434765919"
}
Response Meaning
201 Created
200 This externalRef already names a patient — the existing one is returned
400 Invalid field, or an unexpected one such as organizationId
409 The NHS number already belongs to a different patient here

Retries are safe

externalRef is the idempotency key. Sending the same create twice returns the same patient — the second call answers 200 instead of 201 and creates nothing. This is deliberate: a request that times out has usually succeeded, and a blind retry must not produce a second record for one person. Half that person's readings attaching to each copy is the failure this design exists to prevent.

So: on a timeout, retry the same request unchanged. Do not generate a new externalRef.

The 201 versus 200 distinction lets you tell a first sync from a replay without either being an error.


Attaching a device

Devices are physical and are allocated to your organization by Oryen. List them:

GET /api/v1/organization/devices

Then attach one, naming both sides the way you know them:

POST /api/v1/organization/device-assignments

{
  "patientExternalRef": "EHR-00042",
  "deviceSerialNumber": "ORY-BP-2041",
  "consentConfirmed": true
}

consentConfirmed is required rather than defaulted. You hold the relationship with the patient, so you assert their consent; monitoring somebody without it must not be reachable by leaving a field out.

Assignment is what makes readings work. Telemetry from a device with no active assignment cannot be attributed to a patient, is parked as an orphan, and never becomes a reading. If readings are not appearing, check the assignment first.

Ending an assignment:

POST /api/v1/organization/device-assignments/{assignmentId}/end
{ "notes": "Device returned" }

Why an assignment may be refused

400 message Cause
Device already has an active assignment End the current one first
Create an active organization rental before starting patient monitoring The device is not yet contracted to you — contact Oryen
This rental is not available for patient monitoring Rental status does not permit monitoring
Rental is linked to a different patient That device is committed elsewhere

These are commercial and safety gates, not transient errors. Retrying will not clear them.


Reading data back

GET /api/v1/organization/readings/latest
GET /api/v1/organization/patients/{patientRef}/readings
GET /api/v1/organization/alerts
GET /api/v1/organization/device-assignments

Every reading carries patientExternalRef, readingType, measuredAt, and a detail object holding the measured values for that type.

Prefer webhooks to polling where you can — your administrator configures endpoints in the Oryen portal, and Oryen will push reading.created and alert.created rather than making you ask.


Errors

Status Meaning Retry?
400 Malformed or invalid request No — fix the request
401 Key missing, malformed, unknown, or disabled No — check the key
403 Key lacks the scope, IP not allowlisted, or organization API access disabled No
404 Not in your organization, or does not exist No
409 Conflicts with an existing record (e.g. NHS number) No — reconcile first
429 Rate limited Yes, after a pause
5xx Server-side Yes, with backoff

401 is intentionally vague about why a key failed. The precise reason is recorded in your organization's API request log, visible in the portal — every refused request is logged there, including the ones you did not expect to make.

A 404 never distinguishes "belongs to another organization" from "does not exist". That is deliberate and not a bug to work around.


Withheld records

A patient under restricted processing (UK GDPR Art. 18) is withheld from this API entirely — their record, readings and alerts. Requests for them return 403 with a message naming the restriction, rather than 404, so you can tell a withheld record from a deleted one and stop retrying.


Before you go live

  • Key stored in a secret manager, never in source control
  • IP allowlist set, unless your egress addresses rotate
  • Only the scopes you use are granted
  • Timeout handling retries the same request rather than minting a new externalRef
  • 429 handled with backoff
  • 4xx treated as terminal, not retried in a loop
  • NHS number sent where you hold one
  • Someone owns the API request log in the portal