ZevCampaign Docs
Sign up

API Reference

Errors

The error shape, the types, and the codes worth handling.

Every error has the same shape.

{
  "error": {
    "type": "invalid_request_error",
    "code": "topic_not_found",
    "message": "No topic with that id on this workspace. Check the value against your topics list.",
    "param": "topic_id"
  }
}
  • type — the broad category. Branch on this.
  • code — the specific reason. Match on this when you need to.
  • message — written for a human. Safe to log, not meant to be parsed.
  • param — which field caused it, when one field did.

Match on code, never on message. Messages get reworded; codes do not.

Types

TypeStatusMeaning
authentication_error401The key is missing, malformed or revoked
permission_error403The key is valid but may not do this
invalid_request_error400Something about the request is wrong
not_found_error404No such resource on this workspace
rate_limit_error429Too many requests. See rate limits

A 5xx means the fault is ours. Retry with backoff.

Codes worth handling

contact_unsubscribed — you tried to create or update a contact who has opted out. Nothing was changed. This is not a failure to work around: see consent. Skip them and carry on.

publishable_key_not_allowed — a publishable key reached something other than /v1/subscribe. Almost always a secret key that should have been used on the server.

origin_not_allowed — a publishable key was used from a domain it is not allowed on. Add the domain, or check you have not shipped a staging key.

topic_not_found — no such topic on this workspace. Also returned for an archived topic, so a caller cannot probe which ids ever existed.

topic_not_on_key_brand — the key is scoped to one brand and that topic belongs to another.

invalid_limit — limit was outside 1–100. We refuse rather than quietly clamp, so you find out now instead of wondering why page sizes look odd.

invalid_cursor — the cursor was not one we issued. Pass meta.next_cursor back exactly as given; do not construct one.

team_inactive — the workspace cannot act right now, usually billing. See plans and billing.

Validation errors

A malformed body returns invalid_request_error with param naming the field.

{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_failed",
    "message": "email must be a valid email address.",
    "param": "email"
  }
}

Unknown fields are rejected rather than ignored. A typo’d frist_name fails loudly instead of silently dropping the value.

Retrying

Retry 429 and 5xx with exponential backoff. Do not retry 4xx otherwise — the request will fail the same way every time.

Creating a contact is idempotent on the email address, so a retry after a timeout merges rather than duplicating.

Updated at, Saturday, October 10, 2026