Errors
Errors are RFC 9457 problem details, sent as application/problem+json:
{ "type": "https://docs.rhinorelay.com/api/errors/validation-failed/", "title": "Validation failed", "status": 422, "code": "validation_failed", "detail": "The request body is invalid. See errors.", "requestId": "req_01J9Z8X7W6V5T4S3R2Q1P0N9M8", "errors": [ { "path": "email", "message": "invalid email address" } ]}codeis stable: branch on it, not ontitleordetail.typelinks to the error’s page below.detailexplains the error in words and never repeats the values you sent, so errors are safe to log.errors, on validation errors, lists each problem bypath, again without your values.requestIdis also in every response’sx-request-idheader. Quote it if you contact support.
Every code
Section titled “Every code”The API returns these 33 codes and no others.
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request | Malformed JSON or headers. |
| 401 | unauthenticated | The credential is missing or invalid. |
| 402 | entitlement_inactive | The subscription ended and the grace period is over. Unsubscribe, erasure, export and reads keep working. |
| 403 | forbidden | The credential doesn't carry the scope this endpoint needs. |
| 404 | not_found | No such resource in this tenant, or an invalid token. |
| 409 | tenant_disconnected | The tenant's role or stack is unavailable. Check /health. |
| 409 | contact_suppressed | The address is unsubscribed, bounced, complained, cleaned or erased. |
| 409 | email_taken | Another contact already has this address. |
| 409 | cannot_resubscribe | Bounced, complained and cleaned contacts can't be resubscribed. |
| 409 | segment_in_use | A draft, scheduled or sending campaign uses this segment. |
| 409 | not_draft | Only draft campaigns can change or be deleted. |
| 409 | invalid_state | The campaign's state doesn't allow this action. |
| 409 | quota_reserve_exhausted | Test sends would exceed the daily quota reserve. |
| 409 | not_ready | The import isn't ready to commit yet. |
| 409 | already_committed | The import has already been committed. |
| 409 | idempotency_conflict | The Idempotency-Key was used with a different request. |
| 412 | version_conflict | If-Match doesn't match the resource's current version. |
| 413 | batch_too_large | Over 1,000 items or 1 MB. |
| 422 | validation_failed | The request body or parameters are invalid. See errors[]. |
| 422 | consent_required | Subscribed contacts need a consent record. |
| 422 | segment_invalid | The segment definition is invalid (over 3 levels, over 50 conditions, or an unknown operator). |
| 422 | template_invalid | The template is missing {{ unsubscribe_url }} or {{ footer_address }}, doesn't parse, or is over 380 KB. |
| 422 | from_domain_unverified | fromEmail must be on the tenant's verified sending domain. |
| 422 | render_failed | The template failed to render with the given contact or sample. |
| 422 | schedule_checks_failed | One or more pre-send checks failed. See errors[] for each check and its fix. |
| 422 | acknowledge_mismatch | Resume needs acknowledge equal to the campaign's pauseReason. |
| 422 | mailchimp_auth_failed | Mailchimp rejected the API key or OAuth grant. |
| 422 | stack_not_found | The tenant template stack wasn't found in the registered account and Region. |
| 422 | role_assume_failed | Our service couldn't assume the tenant role with the issued external ID. |
| 421 | wrong_region | This tenant's data lives in another Region. Call https://api.<region>.rhinorelay.com (the console's Setup page shows your API host). |
| 429 | rate_limited | Too many requests. Retry after the Retry-After header. |
| 500 | internal | Something went wrong on our side. Quote requestId to support. |
| 503 | dependency_unavailable | An AWS dependency is unavailable. Retry with the same Idempotency-Key. |
Any authenticated endpoint can return 400, 401, 403, 409 tenant_disconnected, 421 wrong_region, 429, 500 and 503. The API reference lists the other codes each endpoint can return.
Retry or fix?
Section titled “Retry or fix?”- Retry
429after theRetry-Afterseconds, and500and503with the sameIdempotency-Key. - Fix the request for
400,404,412,413and422. - Fix your setup for
401,402,403,409 tenant_disconnectedand421: the key, the subscription, the scope, the connection to your stack or your Region’s API host. - Read the state for the other
409s: the resource isn’t in a state that allows what you asked.