Skip to Content
API access is available to organizations with a signed BAA. Request API access →
Errors

Errors

Failed requests return a standard HTTP status code and an RFC 9457  problem details body with Content-Type: application/problem+json. Branch on the code field, not the human-readable text.

Response · 403 Forbidden
{ "type": "https://www.bloomtext.com/developers/api/errors/#insufficient_scope", "title": "Forbidden", "status": 403, "code": "insufficient_scope", "detail": "This endpoint needs the messages.write scope, and the user didn't grant it.", "request_id": "0b6c2d1e-5f4a-4c3b-9a8d-7e6f5a4b3c2d", "field_errors": [] }

The problem object

typeURLRequired

Link to the documentation for this error.

titlestringRequired

Short, human-readable summary of the status.

statusintegerRequired

The HTTP status code, repeated for convenience.

codestringRequired

Machine-readable error code. See Error codes.

detailstring

Explanation of this specific occurrence.

request_idUUIDRequired

Unique ID for the request. Include it when you contact support.

field_errorsarray of FieldErrorRequired

Per-field problems for 422 responses. Empty otherwise.

Show child attributes
pathstringRequired

JSON pointer to the field, like /body, or the query parameter or header name.

codestringRequired

Machine-readable validation code, like too_long or required.

messagestringRequired

Human-readable explanation.

HTTP status codes

StatusMeaningRetry?
200, 201, 204Success.No
400The request is malformed.No, fix the request.
401The API key or access token is missing, expired, or revoked.After refreshing an OAuth token.
403The credential lacks the scope, or an API key called an OAuth-only endpoint.No
404The resource doesn’t exist, or it’s a conversation the connected admin isn’t in.No
409An idempotency or state conflict.Sometimes. See the code.
422A field failed validation.No, fix the fields.
429Rate limited.Yes, after Retry-After seconds.
500, 503A temporary problem on our side.Yes, with backoff and the same Idempotency-Key.

Error codes

CodeStatusWhat to do
invalid_request400Check the JSON syntax and query string.
range_required400With an API key, List messages needs after, patient_id, or conversation_id. See Read messages.
patient_filter_required400Find patients needs phone, mrn, or both. See Patients.
invalid_query400The q search query can’t be parsed. detail points at the problem. See Search.
invalid_token401API key: check it hasn’t been deleted. OAuth: refresh the access token. If the refresh fails with invalid_grant, the admin must reconnect your app. See When a connection ends.
insufficient_scope403The credential lacks the scope listed on the endpoint’s reference page. Create a key with that scope, or send the admin through the authorize URL again.
oauth_required403API keys can’t call this endpoint. Everything under /me, and the staff directory, requires an OAuth token.
not_found404Check the ID. Conversations the connected admin isn’t in also return this.
idempotency_key_reused409Use a new Idempotency-Key for a different request.
idempotency_request_in_progress409The original request is still running. Retry shortly.
ambiguous_recipient409The phone number belongs to several patients. Pick one from candidates and send with patient_id. See Send messages to patients.
campaign_not_editable409The campaign’s status doesn’t allow that change. See Campaigns.
campaign_not_startable409The campaign is already running, completed, stopped, or archived.
campaign_not_running409Only a running campaign can be paused. Only a running or paused campaign can be stopped.
campaign_not_deletable409Only a draft campaign can be deleted. Archive a started one instead.
validation_failed422Fix each field listed in field_errors.
campaign_empty422Add recipients before starting the campaign.
from_required422The organization has several phone numbers and no default. Pass from, using a number from List phone numbers.
no_contact_method422The patient has no phone number for SMS, or no phone or email for a secure message. Update the patient.
patient_opted_out422The patient replied STOP. Send with channel: secure to deliver by email.
rate_limited429Wait Retry-After seconds, then retry.
internal_error500Retry with backoff. If it persists, contact support with the request_id.
service_unavailable503Retry with backoff.

Handle errors

const response = await fetch(url, options) if (!response.ok) { const problem = await response.json() switch (problem.code) { case 'invalid_token': // Refresh the access token and retry once. If refreshing fails, ask the user to reconnect. break case 'rate_limited': await new Promise((r) => setTimeout(r, Number(response.headers.get('Retry-After')) * 1000)) break default: throw new Error(`${problem.status} ${problem.code}: ${problem.detail} (request ${problem.request_id})`) } }

The OAuth token endpoint, https://app.bloomtext.com/oauth/token, is the one exception. It returns standard OAuth errors like invalid_grant instead of problem details. See Token endpoint errors.

Every response, success or error, includes an X-Request-Id header with the same value as request_id. Log it alongside your own request logs.

Last updated on