Docs/Getting Started

Errors

The error object, every error code with its HTTP status and type, and how to handle and retry failures.

The API uses standard HTTP status codes. 2xx means success, 4xx means something in the request needs to change, and 5xx means something went wrong on Rehabify's side.

The error object

Every error response has the same shape:

{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_error",
    "message": "patient.phone must be a valid phone number (E.164, e.g. +2348012345678).",
    "param": "patient.phone",
    "request_id": "req_5f2c9a1b7d3e4f60a1b2c3d4",
    "doc_url": "https://docs.physioaroundme.com/getting-started/errors#validation_error"
  }
}
FieldDescription
typeThe broad category of error (see the table below).
codeA stable, machine-readable code. Branch on this value.
messageA human-readable explanation. It may change over time, so don't parse it.
paramThe field or query parameter at fault, such as patient.phone. Present only when a specific field is at fault.
request_idThe request's ID. It matches the X-Request-Id header. Quote it to support.
doc_urlA link to this page, anchored at the error code.
existingOnly on duplicate_partner_reference: the id and tracking_code of the referral that already exists.

Error types

typeUsed for
invalid_request_errorMalformed requests, invalid fields, missing consent, inactive links and idempotency misuse
authentication_errorMissing or invalid API key
permission_errorYour organisation or key isn't allowed to do this
not_found_errorThe resource or endpoint doesn't exist in this environment
conflict_errorThe request conflicts with existing state
rate_limit_errorToo many requests
api_errorA problem on Rehabify's side, or a feature that isn't available yet

All error codes

HTTPtypecodemeaning
400invalid_request_errorinvalid_jsonBody is not valid JSON
400invalid_request_errorinvalid_parameterA query parameter is invalid (param set)
401authentication_errormissing_api_keyNo key supplied
401authentication_errorinvalid_api_keyKey unknown or revoked
403permission_errorpartner_inactiveOrganisation not approved / suspended
403permission_errorproduction_access_requiredLive key used but production access is not approved
403permission_errorsandbox_onlySandbox-only endpoint called with a live key
404not_found_errorreferral_not_foundNo referral with that id / tracking code / partner_reference in this environment
404not_found_errorreferral_link_not_foundReferral link not found
404not_found_errorresource_not_foundUnknown endpoint
409conflict_errorduplicate_partner_referenceA referral with this partner_reference already exists in this environment. error.existing = { "id", "tracking_code" }
409conflict_erroridempotency_request_in_progressConcurrent request with the same Idempotency-Key
409conflict_errorwebhook_endpoint_not_configuredNo webhook endpoint for this environment (sandbox trigger)
410invalid_request_errorlink_inactivePublic lead endpoint: link inactive or expired
422invalid_request_errorvalidation_errorField failed validation (param set)
422invalid_request_errorconsent_requiredconsent.granted must be true
422invalid_request_errorpatient_ineligibleSandbox scenario +2348000000004
422invalid_request_erroridempotency_key_reusedIdempotency-Key reused with a different body
422invalid_request_errorinvalid_status_transitionSandbox advance to an invalid status
429rate_limit_errorrate_limit_exceededToo many requests
500api_errorinternal_errorUnexpected error (safe to retry with the same Idempotency-Key)
501api_errorfeature_not_availableEndpoint not yet available in live (eligibility)
503api_errorservice_unavailableTemporary outage — retry with backoff

Handling errors

SituationRetry?How
429 rate_limit_exceededYesWait for Retry-After seconds, then retry with backoff.
500 internal_error, 503 service_unavailable, network timeoutsYesExponential backoff with jitter, using the same Idempotency-Key.
409 idempotency_request_in_progressYesWait a moment, then retry with the same key and body.
409 duplicate_partner_referenceNoUse error.existing to fetch the referral that already exists.
Other 4xx errorsNoFix the request first. Retrying unchanged gives the same error.

Conventions includes a ready-made retry helper for Node.js and Python.

400 Bad Request

invalid_json

The request body isn't valid JSON. Check for trailing commas, unescaped quotes or a truncated body, and send Content-Type: application/json.

invalid_parameter

A query parameter is invalid, and param names it. Common causes: limit outside 1–100, a status value that isn't allowed for that endpoint, or a timestamp filter that isn't ISO-8601.

401 Unauthorized

missing_api_key

The request had no API key. Send Authorization: Bearer <key> or X-API-Key: <key>. See Authentication.

invalid_api_key

The key isn't recognised or has been revoked. Check for copy errors and stray whitespace, and make sure your deployment loads the right secret. If the key was lost or revoked, create a new one in Developers → API keys.

403 Forbidden

partner_inactive

Your organisation hasn't been approved yet, or has been suspended. Contact partners@physioaroundme.com.

production_access_required

You used a live key, but your organisation doesn't have approved production access, either because it hasn't been granted yet or because it was suspended. Request production access in the Partner Portal, or use a sandbox key. See Production access.

sandbox_only

You called a sandbox-only endpoint (/sandbox/*) with a live key. Use a sk_test_ key.

404 Not Found

referral_not_found

No referral with that id, tracking_code or partner_reference exists in this environment. You also get this error when the referral belongs to another partner, or to the other environment (for example, a sandbox referral fetched with a live key).

No referral link matches the id (for PATCH /partners/referral-links/{id}) or the public_code (for the public lead endpoint).

resource_not_found

The endpoint doesn't exist. Check the path and make sure it includes /v1, for example https://api.physioaroundme.com/v1/partners/referrals.

409 Conflict

duplicate_partner_reference

A referral with this partner_reference already exists in this environment. The error tells you which one:

{
  "error": {
    "type": "conflict_error",
    "code": "duplicate_partner_reference",
    "message": "A referral with partner_reference HMO-REF-2026-0091 already exists.",
    "request_id": "req_8a1d4c7e2b9f4a3c8d6e1f0a",
    "doc_url": "https://docs.physioaroundme.com/getting-started/errors#duplicate_partner_reference",
    "existing": { "id": "jd7f3k2m9x1q8w4e5r6t7y8u9i0o1p2a", "tracking_code": "RHB-4829173655" }
  }
}

If this is the same patient you referred before, use existing.id to fetch that referral instead of creating a new one. If it's a different referral, send a different partner_reference.

idempotency_request_in_progress

Another request with the same Idempotency-Key is still being processed. Wait briefly, then retry with the same key and body. You'll get the original response.

webhook_endpoint_not_configured

POST /sandbox/trigger-webhook was called, but no webhook endpoint is configured for this environment. Set one in Developers → Webhooks in the Partner Portal.

410 Gone

Returned by the public lead endpoint when the referral link is inactive or past its expires_at. Reactivate the link (PATCH /partners/referral-links/{id} with "status": "active") or create a new one. See Referral links.

422 Unprocessable Entity

validation_error

A field failed validation. param names the field (for example patient.phone) and message explains the rule. Field rules are listed in Create a referral.

consent.granted is missing or isn't true. Rehabify only accepts referrals for patients who have agreed to be contacted. Capture consent first, then send "consent": { "granted": true }.

patient_ineligible

Returned in sandbox when patient.phone is the magic number +2348000000004. No referral is created. Use it to test how your system handles a rejected referral.

idempotency_key_reused

The Idempotency-Key was already used in the last 24 hours with a different request body. Use a new key whenever the body changes.

invalid_status_transition

POST /sandbox/referrals/{id}/advance asked for a status that can't follow the current one: either a move backwards, or a move out of a terminal status. See Sandbox & testing.

429 Too Many Requests

rate_limit_exceeded

You've exceeded your rate limit: 10 requests per second in sandbox, or 20 per second in live (100 per second on enterprise contracts). The public lead endpoint allows 5 requests per 10 minutes per IP address. Wait for the number of seconds in the Retry-After header, then retry with backoff.

500 Internal Server Error

internal_error

Something unexpected went wrong on Rehabify's side. It's safe to retry with the same Idempotency-Key. If the error persists, contact support with the request_id.

501 Not Implemented

feature_not_available

The endpoint isn't available in live yet. Currently this applies to POST /partners/eligibility, which is coming soon. Only a simulated preview is available, in sandbox.

503 Service Unavailable

service_unavailable

A temporary outage. Retry with exponential backoff, using the same Idempotency-Key for POST requests.

Errors | Rehabify Docs | Physio Around Me by Rehabify Health