Errors
BloomText uses standard HTTP status codes and returns RFC 9457 problem details with Content-Type: application/problem+json. Branch on the code field, not the human-readable text.
{
"type": "https://www.bloomtext.com/developers/api/errors/#conversation_membership_required",
"title": "Forbidden",
"status": 403,
"code": "conversation_membership_required",
"detail": "The app user is not a participant in this conversation.",
"request_id": "0b6c2d1e-5f4a-4c3b-9a8d-7e6f5a4b3c2d",
"field_errors": []
}The problem object
typeURLRequiredLink to the documentation for this error.
titlestringRequiredShort, human-readable summary of the status.
statusintegerRequiredThe HTTP status code, repeated for convenience.
codestringRequiredMachine-readable error code. See Error codes.
detailstringExplanation of this specific occurrence.
request_idUUIDRequiredUnique ID for the request. Include it when you contact support.
field_errorsarray of FieldErrorRequiredPer-field problems for 422 responses. Empty otherwise.
Show child attributes
pathstringRequiredJSON pointer to the field, like /body, or the query parameter or header name.
codestringRequiredMachine-readable validation code, like too_long or required.
messagestringRequiredHuman-readable explanation.
HTTP status codes
| Status | Meaning | Retry? |
|---|---|---|
200, 201, 202, 204 | Success. | No |
400 | The request is malformed. | No, fix the request. |
401 | The API key is missing, revoked, or invalid. | No, fix the key. |
403 | The key lacks the scope, or the app user isn’t a participant. | No |
404 | The resource doesn’t exist or isn’t visible to this key. | No |
409 | An idempotency or state conflict. | Sometimes. See the code. |
422 | A field failed validation. | No, fix the fields. |
429 | Rate limited. | Yes, after Retry-After seconds. |
500, 503 | A temporary problem on our side. | Yes, with backoff and the same Idempotency-Key. |
Error codes
| Code | Status | What to do |
|---|---|---|
invalid_request | 400 | Check the JSON syntax and query string. |
unauthorized | 401 | Check the Authorization header and that the key hasn’t been revoked. |
insufficient_scope | 403 | Ask an admin to add the scope listed on the endpoint’s reference page. |
conversation_membership_required | 403 | Add your app user to the conversation. |
not_found | 404 | Check the ID. Resources outside your app user’s conversations also return this. |
idempotency_key_reused | 409 | Use a new Idempotency-Key for a different request. |
idempotency_request_in_progress | 409 | The original request is still running. Retry in a moment. |
participant_not_in_organization | 422 | Only members of your organization can be added to a conversation. |
validation_failed | 422 | Read field_errors for each field to fix. |
rate_limited | 429 | Wait Retry-After seconds, then retry. |
internal_error | 500 | Retry with backoff. Contact support with the request_id if it persists. |
service_unavailable | 503 | Retry with backoff. |
Handle errors
JavaScript
const response = await fetch(url, options)
if (!response.ok) {
const problem = await response.json()
switch (problem.code) {
case 'conversation_membership_required':
// Ask an admin to add the app user to this conversation.
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})`)
}
}Every response, success or error, includes an X-Request-Id header with the same value as request_id. Log it with your own request logs.