Skip to content

Error codes ​

Every failed request carries a stable error.code. Match on that, never on error.message — messages are written for people and change.

json
{
  "success": false,
  "status_code": 422,
  "error": {
    "code": "notifyzr.send.error.sender_domain_not_verified",
    "message": "Sender domain 'example.com' is not verified for this organization",
    "issues": []
  },
  "payload": null
}

Codes are namespaced notifyzr.<domain>.error.<name>. A code is never reused for a different meaning, and a new one may appear in any release — treat an unrecognised code as the generic failure its status code implies.

Common ​

CodeStatusMeaning
notifyzr.common.error.unknown500Unhandled failure.
notifyzr.common.error.service_unavailable503A dependency (broker, database) is down. Retry.
notifyzr.common.error.rate_limited429See Rate limiting.
notifyzr.common.error.validation422Schema validation failed. Per-field detail is in error.issues.
notifyzr.common.error.http.not_found404No such route, or no such record in your organization.
notifyzr.common.error.http.method_not_allowed405Wrong verb for that route.

Authentication ​

CodeStatusMeaning
notifyzr.common.error.auth.no_header401No X-API-Key header.
notifyzr.common.error.auth.invalid_header401The header is present but unusable.
notifyzr.common.error.auth.invalid_credentials401Credentials rejected.
notifyzr.common.error.auth.forbidden403Authenticated, not permitted.
notifyzr.common.error.apikey.invalid401Unknown key.
notifyzr.common.error.apikey.malformed401The key is not shaped like a key.
notifyzr.common.error.apikey.unauthorized401Invalid or inactive key.
notifyzr.common.error.apikey.expired401Past its expires_at.

Expired, revoked and invalid are the same answer

All three are 401 with no hint about which. Anything else would let a caller probe which keys have existed.

Sending ​

CodeStatusMeaning
notifyzr.send.error.no_recipients422No recipients — including the case where every recipient was on the suppression list.
notifyzr.send.error.no_body422Neither a body nor a template_id.
notifyzr.send.error.sender_required422No sender address on a channel. There is no implicit from-address.
notifyzr.send.error.sender_domain_not_verified422The sender's domain is not a verified domain of this organization.
notifyzr.messenger.error.send_failed500The send could not be accepted.
notifyzr.messenger.error.channel_unsupported422Unknown channel type.
notifyzr.messenger.error.channel_not_implemented501Known type, no sender for it.
notifyzr.message.error.not_found404No such message.

All four send errors are raised before the message is recorded and before quota is spent, so a refused send costs nothing.

Contacts ​

CodeStatusMeaning
notifyzr.contact.error.not_found404
notifyzr.contact.error.email_exists422Addresses are unique per organization.
notifyzr.contact.error.property_invalid_value422A property value does not match its declared type.
notifyzr.contact_property_definition.error.not_found404
notifyzr.contact_property_definition.error.key_exists422
notifyzr.contact_property_definition.error.limit_reached422
notifyzr.contact_import.error.not_found404
notifyzr.contact_import.error.unsupported_media_type415Send multipart/form-data or JSON with a csv string.
notifyzr.unsubscribe.error.not_found404

Segments and broadcasts ​

CodeStatusMeaning
notifyzr.segment.error.not_found404
notifyzr.segment.error.slug_exists422
notifyzr.segment.error.invalid_filter422The filter tree broke a rule. The message names which.
notifyzr.segment.error.limit_reached422
notifyzr.segment.error.unknown_contacts422A contact id given to add as a member is not in your organization. Nothing was added.
notifyzr.segment.error.member_not_found404The contact was not added to the segment by hand.
notifyzr.broadcast.error.not_found404
notifyzr.broadcast.error.not_editable422Only a draft can be edited.
notifyzr.broadcast.error.not_deletable422Only a draft can be deleted.
notifyzr.broadcast.error.already_sent422It has left the draft state.

Templates ​

CodeStatusMeaning
notifyzr.template.error.not_found404
notifyzr.template.error.not_published422A draft cannot be used to send.
notifyzr.template.error.body_required422Publishing needs at least one body.
notifyzr.template_folder.error.not_found404
notifyzr.template_folder.error.depth_exceeded422Folders nest three levels.
notifyzr.template_folder.error.cycle422A folder cannot be moved inside itself.
notifyzr.template_folder.error.limit_reached422

Automations ​

CodeStatusMeaning
notifyzr.automation.error.not_found404
notifyzr.automation.error.invalid_trigger422Not an event in the catalog.
notifyzr.automation.error.invalid_conditions422
notifyzr.automation.error.invalid_actions422
notifyzr.automation.error.incomplete_graph422The graph does not satisfy the rules a published automation must. A draft is not held to them.

Forms ​

CodeStatusMeaning
notifyzr.form.error.not_found404Also returned for an inactive form's submission endpoint.
notifyzr.form.error.no_fields422
notifyzr.form.error.invalid_fields422
notifyzr.form.error.unsupported_media_type415The submission endpoint takes form encodings only.

Domains, channels and webhooks ​

CodeStatusMeaning
notifyzr.domain.error.not_found404
notifyzr.domain.error.invalid422Not a usable domain name.
notifyzr.domain.error.exists422Already added to this organization.
notifyzr.channel.error.not_found404
notifyzr.channel.error.invalid422Missing or malformed credentials for that channel type.
notifyzr.webhook.error.not_found404
notifyzr.webhook.error.invalid_url422Must be an absolute http(s) URL.

Quota ​

CodeStatusMeaning
notifyzr.quota.error.exceeded422A plan ceiling was reached. GET /v1/usage says which.

Released under the Apache 2.0 License.