Read an error
Every refusal is an RFC 9457 Problem Details body with a status that says what kind of problem it is, a code to branch on, and a list of every field to fix.
On this page
Whatever went wrong, the body is sent as application/problem+json:
{
"type": "https://developers.practor.app/guides/errors#validation-failed",
"title": "Some fields are missing or wrong",
"status": 422,
"detail": "Fix the fields listed in errors and send it again.",
"code": "validation_failed",
"requestId": "x9k2m4p7q1w8e3r6t5y0u2i4",
"errors": [
{ "field": "lastName", "code": "required", "message": "Send lastName." },
{ "field": "birthDate", "code": "invalid", "message": "birthDate must be a real date, written YYYY-MM-DD" }
]
}Branch on code: it stays the same from release to release, while detail and title may be reworded. detail is a sentence you can show a person. errors lists every field, query parameter or header that is missing (required) or wrong (invalid), all at once, so you can fix a request in one round trip. A field in the body is named by its path, such as procedures.1.code.
requestId is the same as the X-Request-Id header every answer has. Quote it when you contact support, and we can find the request in seconds.
Statuses
| Status | What happened | What to do |
|---|---|---|
400 | A query parameter or header is missing or malformed, the body isn't JSON, or a cursor wasn't one Practor sent | Read errors: it names the parameter |
401 | No key, or a key that can't be used: unknown, revoked, expired, its client suspended, or called from an address the client may not use. All of these look the same | Check the key, then ask the practice to look the request up in its audit log. See Authenticate |
403 | The client lacks the permission, or the practice's Integrations add-on is off | The practice owner adds the permission named in detail |
404 | The record doesn't exist in this practice | A record in another practice answers exactly like a missing one |
405 | The endpoint doesn't take this method | The Allow header says which one it does |
409 | A duplicate (such as a second patient with your externalId), or the same Idempotency-Key is still running | detail names the existing record |
413 | The body is over 256 KB | Split the request |
415 | The body wasn't sent as application/json | Set Content-Type |
422 | The JSON is valid but breaks a rule, such as an unknown diagnosis code | Fix every entry in errors |
429 | Too many requests | See Rate limits |
500 | Something failed on our side | Retry with the same Idempotency-Key. If it keeps happening, send us the requestId |
Codes
Each error's type links to its section here.
Invalid request
invalid_request, status 400. A query parameter, a header or the body is malformed. errors names which.
Invalid cursor
invalid_cursor, status 400. The cursor isn't one Practor sent. Send nextCursor exactly as it came, with the same filters as the page it came from.
Validation failed
validation_failed, status 422. Fields in the body are missing or wrong. Fix every entry in errors.
Unauthenticated
unauthenticated, status 401. The key is missing or can't be used.
Forbidden
forbidden, status 403. The client lacks the permission detail names.
Addon inactive
addon_inactive, status 403. The practice's Integrations add-on is off.
Not found
not_found, status 404. The record doesn't exist in this practice.
Method not allowed
method_not_allowed, status 405. Use the method in the Allow header.
Conflict
conflict, status 409. Another request is in the way, such as one with the same Idempotency-Key still running. Retry shortly.
Duplicate
duplicate, status 409. The record already exists. detail names it.
Business rule
business_rule, status 409, 422 or 400. The request is well formed but Practor won't do it, such as billing a visit that isn't finished. detail says why.
Unprocessable
unprocessable, status 422. The request couldn't be completed, such as a visit that couldn't be priced. detail says why.
Idempotency key reused
idempotency_key_reused, status 422. The Idempotency-Key was already used with a different body. Use a new key for each new record.
Payload too large
payload_too_large, status 413. The body is over 256 KB.
Unsupported media type
unsupported_media_type, status 415. Send the body as application/json.
Rate limited
rate_limited, status 429. Wait the Retry-After seconds, then retry.
Internal error
internal_error, status 500. Retry with the same Idempotency-Key.
Service unavailable
service_unavailable, status 503. Practor couldn't record the request in the practice's audit trail, so it withheld the answer. Retry after the Retry-After seconds.