Macha

Zendesk API Errors (401, 422, 429) and How to Fix Them

Abbas, Customer Support & AI, Macha

Written by

Ankeet Guha, Co-founder & CTO, Macha

Reviewed by

Published June 30, 2026

Updated June 30, 2026

You fired off a request to the Zendesk REST API, and instead of clean JSON you got a number: `401`, `422`, or — the classic that shows up only in production, never in testing — `429`. The Zendesk API is well-behaved, but its errors are terse. The status code tells you which class of thing went wrong; the response body (which a lot of people never read) usually tells you exactly what.

Zendesk API Errors (401, 422, 429) and How to Fix Them

This is a developer's field guide to the Zendesk API errors you'll actually hit, with the real cause and the exact fix for each, plus copy-paste request and response examples. If you want the conceptual background first — base URLs, auth, pagination — start with the Zendesk API explained; this post assumes you're already making calls and just want the error to stop. Everything here is verified against Zendesk's developer docs as of June 2026; rate-limit numbers in particular change, so confirm them in your own account.

First: read the error, don't guess

Before any specific fix, build the habit that resolves most Zendesk API errors in one pass — read the whole response, not just the status line. Two things carry the signal:

  • The status code classifies the failure: 4xx means you sent something wrong (auth, permissions, validation, rate); 5xx means Zendesk had a problem.
  • The response body names the specifics. Zendesk returns a JSON body for most 4xx errors with an error key and often a details map pointing at the offending field. (One exception: some 400 Bad Request responses come back as text/plain for API-level errors, so don't assume JSON.)

Always log the status code, the response body, and the response headers. The headers carry Retry-After on a 429, and dumping the Authorization header (carefully, in a dev environment) is the single fastest way to debug a 401. Here's the minimum you want to capture:

curl -sS -D - \
  -u "[email protected]/token:YOUR_API_TOKEN" \
  "https://your_subdomain.zendesk.com/api/v2/tickets/123.json"
# -D - prints response headers (status line, Retry-After, X-Rate-Limit) to stdout

With that in hand, the codes below become quick to diagnose.

401 Unauthorized — Zendesk can't authenticate you

A 401 means Zendesk couldn't identify who's calling. It never even got to checking permissions — the credentials themselves didn't parse or weren't accepted. This is almost always an auth-header problem, and it's the most common Zendesk API error by a wide margin.

The correct auth header patterns

There are two auth methods you'll use, and mixing them up is the #1 cause of 401.

API token via Basic auth. The username is not just your email — it's your email with /token appended, then a colon, then the token, all Base64-encoded:

Authorization: Basic base64( {email_address}/token:{api_token} )

So with curl you let -u do the encoding, and the literal /token suffix is required:

# CORRECT — note the /token suffix on the username
curl -u "[email protected]/token:abc123APITOKEN" \
  "https://your_subdomain.zendesk.com/api/v2/users/me.json"

If you build the header yourself, encode [email protected]/token:abc123APITOKEN — for example btoa(${email}/token:${token}) in JS — and send Authorization: Basic <that string>.

OAuth access token via Bearer. OAuth tokens do not go in a Basic header. They use the Bearer scheme:

# CORRECT — OAuth uses Bearer, never Basic
curl -H "Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN" \
  "https://your_subdomain.zendesk.com/api/v2/users/me.json"

Common causes and fixes

  • Omitting the /token suffix. [email protected]:TOKEN is treated as email/password, not email/token — and fails. Add /token.
  • Bad Base64 / hidden whitespace. A trailing newline or space sneaks into the encoded string (common when piping through shell tools). Re-encode and log the exact header.
  • OAuth token sent as Basic (or an API token sent as Bearer). Match the scheme to the credential.
  • Token revoked, expired, or deleted. Someone deleted the API token in Admin Center, or the OAuth token expired. Regenerate it.
  • Password/token access disabled. Admins can switch off password access and/or token access for the API in Admin Center security settings. If basic email:password auth started 401-ing, that's the likely reason — switch to an API token or OAuth.
  • Wrong subdomain or environment. Credentials are scoped to one account. A sandbox token will 401 against production (and vice versa). Confirm the subdomain in the URL matches the account that issued the credential.
Where these credentials live: API tokens and OAuth clients are both created in Admin Center → Apps and integrations → APIs → Zendesk API (the OAuth tab is in the same area). If you can't find a token to regenerate, that's the page.
Zendesk Admin Center → Apps and integrations → APIs → API tokens, where the credentials behind 401/429 errors are created and managed.
Zendesk Admin Center → Apps and integrations → APIs → API tokens, where the credentials behind 401/429 errors are created and managed.

The screenshot above is that admin area — API tokens and OAuth clients are managed under Apps and integrations → APIs. Generate a token there, test it with the users/me.json call above, and a clean 200 confirms your auth header is correct before you debug anything else.

403 Forbidden — authenticated, but not allowed

A 403 is the opposite of a 401 in an important way: Zendesk knows who you are, it just won't let that identity do this. Don't go re-checking your token format — the credential is fine. The problem is permissions or scope.

{
  "error": "Forbidden",
  "description": "You do not have access to this page. Please contact the account owner of this help desk for further help."
}

Common causes and fixes

  • End-user credentials hitting an agent/admin endpoint. Many endpoints require an agent or admin. If you authenticated as an end user (or a token tied to one), agent-only routes return 403. Use credentials with the right role.
  • Agent calling an admin-only action. Some operations (account settings, certain user changes) require an admin. Bump the calling identity's role or use an admin token.
  • OAuth token missing the required scope. Scopes are fixed at token creation — you can't widen them afterward. If a token was minted with read only and you POST, you'll get 403. Mint a new token with the scope you need (e.g. tickets:write).
  • Feature not on your plan. Some endpoints are gated to specific Suite plans or add-ons. If the feature isn't on your plan, even an admin gets 403. Confirm the endpoint is available on your plan tier.
  • IP allowlist restrictions. If the account restricts API access by IP, requests from an unlisted address are rejected. Add your server's IP to the allowlist.
  • Cross-brand or suspended access. Reaching a resource that belongs to another brand, or calling as a suspended/downgraded agent, also returns 403.

The quick triage: if the same credential works on some endpoints but 403s on one, it's a scope/role/plan issue on that endpoint — not your auth.

422 Unprocessable Entity — your data didn't validate

A 422 means your request authenticated, parsed, and was understood — but the content failed Zendesk's validation rules. Your JSON is syntactically fine; a value inside it isn't acceptable. This is the friendliest error to debug because Zendesk tells you exactly which field is wrong — in the details object.

Say you try to create a user with an email that already exists:

curl -u "[email protected]/token:abc123APITOKEN" \
  -X POST "https://your_subdomain.zendesk.com/api/v2/users.json" \
  -H "Content-Type: application/json" \
  -d '{"user": {"name": "Jane Doe", "email": "[email protected]"}}'

Zendesk responds 422 with a body like this:

{
  "error": "RecordInvalid",
  "description": "Record validation errors",
  "details": {
    "email": [
      {
        "description": "Email: [email protected] is already being used by another user",
        "error": "DuplicateValue"
      }
    ]
  }
}

The fix lives in details: the key (email) is the offending field, and the array spells out why (DuplicateValue). (The exact human-readable description string can vary slightly by API version, so match on the structure and the error type rather than the prose.)

Common causes and fixes

  • Missing a required field. Creating a ticket without comment, or a user without name, fails. details will name the blank field (error: "blank"). Add it.
  • Invalid value. A value outside the allowed set — an unknown priority, a malformed date, a non-existent group_id. details flags the field. Send a valid value.
  • Duplicate. As above — an email or external ID already in use (DuplicateValue). Look the existing record up and update it instead of creating a new one, or use a different value.
  • Bad field format. A custom field expecting a number gets a string, or a tag has illegal characters. Match the field's expected type.

A related code worth knowing: 409 Conflict. Zendesk returns it when simultaneous requests touch the same resource. For writes you want to be idempotent, design retries so a replay doesn't double-create — key off your own external ID, check-then-create, and treat a duplicate (422) on retry as "already done" rather than a hard failure.

429 Too Many Requests — you hit the rate limit

A 429 means you exceeded Zendesk's rate limit. It's the error that never shows up in local testing and then floods your logs the moment you run a backfill or a busy sync. The fix is not "send slower and hope" — Zendesk tells you exactly how long to wait.

Honor the Retry-After header

Every 429 comes back with a Retry-After header giving the number of seconds to wait before retrying. Read it and wait — don't immediately hammer again.

HTTP/1.1 429 Too Many Requests
Retry-After: 38
X-Rate-Limit: 700

A minimal, correct retry loop honoring it:

import time, requests

def zendesk_get(url, auth, max_retries=5):
    for attempt in range(max_retries):
        resp = requests.get(url, auth=auth)
        if resp.status_code != 429:
            return resp
        wait = int(resp.headers.get("Retry-After", 2 ** attempt))  # fall back to backoff
        time.sleep(wait)
    resp.raise_for_status()

If Retry-After is ever absent, fall back to exponential backoff (1s, 2s, 4s, 8s…) with a little jitter so parallel workers don't all retry in lockstep.

The rate limits themselves

Zendesk's per-minute account limit for the Support/Help Center API depends on your Suite plan. As of June 2026 the documented per-minute limits are:

Suite planRequests / minute
Team200
Growth400
Professional400
Enterprise700
Enterprise Plus2,500

The High Volume API add-on raises a qualifying plan to 2,500 requests/minute (it sets the limit to 2,500 — it doesn't add 2,500 on top). On top of the account limit, specific endpoints have their own tighter limits: Incremental Exports is about 10 requests/minute (30 with High Volume), Update Ticket throttles to roughly 30 updates per 10 minutes per user per ticket, and some list endpoints throttle once you page deep. These numbers are plan-dependent and Zendesk changes them — treat the table as a starting point and confirm in the rate limits docs and your own account.

Stop hitting it in the first place

Backoff handles the spike; the real fix is making fewer, smarter calls — Zendesk's own best practices for this:

  • Sideload related data. ?include=users,groups pulls associated records in one response instead of an N+1 storm of follow-up calls.
  • Use cursor-based pagination (page[size], links.next) rather than offset paging, which is itself rate-limited past the first pages.
  • Pull bulk data with the Incremental Exports API, not by paging every ticket — it's built for large, periodic syncs.
  • Use bulk endpoints like Update Many Tickets (up to 100 records per request) instead of one call per record.
  • Cache data that doesn't change every minute (groups, custom field definitions, org records) instead of re-fetching it.
  • Throttle proactively — spread requests evenly under your per-minute ceiling rather than bursting.

404 and 5xx — the quick ones

404 Not Found is almost always a URL or ID problem: a typo in the path, a missing .json, a resource that was deleted, or an ID that belongs to a different account/subdomain. Re-check the endpoint path and confirm the record exists with a list call before you fetch it by ID.

5xx (500, 502, 503) means the problem is on Zendesk's side, not yours. Don't refactor your code — check status.zendesk.com for an incident, then retry with backoff. A 503 may include a Retry-After header (e.g. during scheduled maintenance); honor it the same way you do for a 429.

Best practices that prevent most API errors

A short checklist that heads off the errors above before they happen:

  • Store tokens securely. Keep API tokens and OAuth secrets in environment variables or a secrets manager — never in source control or client-side code. Rotate them if exposed.
  • Always read the response body and headers. The details map (422) and Retry-After (429) tell you the fix directly. Log status, body, and headers on every failure.
  • Build retries in from day one. Honor Retry-After, fall back to exponential backoff with jitter, and cap attempts. Make writes idempotent so a retry can't double-create.
  • Minimize calls. Sideload, cache, paginate with cursors, and use bulk endpoints — fewer requests means fewer 429s and a faster integration.
  • Check the status page before debugging a 5xx. Save yourself an hour of chasing a bug that's actually a Zendesk incident.
  • Match scope to need. Mint OAuth tokens with exactly the scopes the integration uses — narrow enough to be safe, wide enough to avoid 403.

Where an AI agent fits in

If you're hitting these errors because you're hand-rolling an integration that reads tickets, drafts replies, tags, and routes, it's worth knowing there's a layer that handles the plumbing for you. Macha is an AI agent layer that runs on top of Zendesk — it's not a help desk and not a Zendesk replacement. Under the hood, Macha talks to Zendesk through the same REST API covered here via its connector, which means it manages the auth handshake, honors rate limits and Retry-After backoff, and deals with pagination and validation so you're not the one writing retry loops and chasing 429s.

Keeping it honest for a dev audience: it's still an integration with its own setup, and it's only as useful as the knowledge and tools you connect it to. On cost, Macha bills per AI action — each automated step an agent takes (drafting a reply, tagging, routing, resolving) — not per ticket or per resolution, because most of the work is the steps along the way, not a single tidy outcome. If your reason for touching the API is "automate repetitive ticket work," that's the line where a managed agent can save you the integration maintenance. You can try it free — 7-day free trial, no credit card required. If you're building the integration yourself, the Zendesk API guide, webhooks, and how the ticketing system models its objects are the references to keep open.

Frequently asked questions

Why am I getting a 401 from the Zendesk API when my token is correct? The most common cause is the username format. For API-token Basic auth the username must be email/token (with the literal /token suffix), not just your email — so the full string you Base64-encode is [email protected]/token:YOUR_TOKEN. Other culprits: sending an OAuth token with Basic instead of Bearer, hidden whitespace in the encoded header, a revoked token, password/token access disabled in Admin Center, or using a sandbox token against production.

What's the difference between a 401 and a 403 on the Zendesk API? A 401 means Zendesk can't authenticate you — it can't tell who's calling (bad or missing credentials). A 403 means it authenticated you fine but you're not authorized for that action — wrong role (end user on an agent endpoint), an OAuth token missing the needed scope, an IP restriction, or a feature not on your plan. If one credential works on some endpoints but 403s on another, it's a permissions issue, not an auth-format one.

How do I find which field caused a Zendesk 422 error? Read the response body. A 422 returns error: "RecordInvalid" with a details object keyed by field name — e.g. details.email with an array describing the problem ("blank", "DuplicateValue", an invalid value). The key is the offending field and the array tells you why. Fix that field and resend.

How do I handle Zendesk API 429 rate limit errors? Read the Retry-After response header — it gives the seconds to wait — then wait that long and retry. If it's missing, fall back to exponential backoff with jitter. Longer term, reduce calls: sideload related records (?include=), use cursor pagination, pull bulk data with Incremental Exports, batch writes with Update Many, and cache slow-changing data.

What are Zendesk's API rate limits? They're per-minute, per-account, and vary by Suite plan — roughly Team 200, Growth/Professional 400, Enterprise 700, Enterprise Plus 2,500 requests per minute, with the High Volume API add-on raising a qualifying plan to 2,500. Specific endpoints (Incremental Exports, Update Ticket, deep list pages) have their own tighter limits. These change over time, so confirm against Zendesk's rate-limits doc and your own account.

A Zendesk API call returns 500 or 503 — is it my code? Probably not. 5xx codes are server-side. Check status.zendesk.com for an active incident or maintenance window, then retry with backoff. A 503 may carry a Retry-After header you should honor.

The bottom line

Zendesk API errors are diagnosable once you read the whole response, not just the status code. 401 is authentication — fix the auth header (email/token for Basic, Bearer for OAuth). 403 is permission — check role, scope, plan, and IP rules; the credential itself is fine. 422 is validation — the details object names the exact bad field. 429 is rate limiting — honor Retry-After, back off, and make fewer calls via sideloading, cursor pagination, bulk endpoints, and caching. 404 is a wrong URL or ID, and 5xx is Zendesk's side, so check the status page before you touch your code. Store credentials securely, build retries in from the start, and read the body every time — do that and most Zendesk API errors fix themselves in a single pass. For the wider picture, see the Zendesk API explained.

Error behavior and rate limits verified against Zendesk's developer documentation, June 2026. Zendesk revises rate limits and API behavior periodically — confirm specifics in the developer docs and your own account.

Macha

About Macha

Macha is an AI agent platform that works on top of the help desk you already use — Zendesk, Freshdesk, Gorgias, or Front — and connects to the rest of your stack, even your own internal systems. Its AI agents resolve tickets and automate entire workflows end to end, all set up in plain English, no code. Learn more about Macha →

Zendesk
5.0 on Zendesk Marketplace

Loved by support teams worldwide

See what support teams are saying about Macha AI.

The application seems excellent to me! We are still testing, and we need support for some details and they were extremely efficient too!

Daniela Costa

Daniela Costa

Head of Support, Seabra

Macha has been a great addition to our support toolkit. It generates clear, well-organized responses that fit naturally into our workflow. One feature we particularly appreciate is its ability to automatically reply in the same language as the ticket.

Marius F

Marius F

Support Head, Zentana

We've been using Macha for a little while now and it's been really great addition so far! It's powerful, convenient, and makes getting work done a lot easier for our agents.

Alexander Wedén

Alexander Wedén

Head of Support

Support team is very helpful and responsive. Really enjoy how lightweight this is within Zendesk itself vs other more intrusive tools.

Cathleen Wright

Cathleen Wright

Zendesk Admin, Cortex IO

So far it's pretty good! Our queries are a little nuanced, so we can't always use it, but it's got enough utility for us. It can even incorporate our bilingual country with greetings in a second language.

Jae Oliver

Jae Oliver

Head of Support, Wise

Really enjoying using Macha, it has made a noticeable difference to our support team in a short amount of time. I really like the ticket summary feature, saves us a lot of time.

Harry Jackson

Harry Jackson

Head of Support, Crumb

Macha AI is a great addition to my workspace! It's powerful, convenient, and it really makes productivity so much easier for our agents!

Dave G

Dave G

Head of Support, Cyber Power Systems

Very impressed! AI integration for Zendesk has certainly come a long way and Macha seems to set the standard for now. This will for sure save lot of time in our support team.

Pauli Juel

Pauli Juel

Head of CS, Dokument24

Macha has been working great for us so far! The auto-responses are accurate and our resolution time has dropped significantly.

Lana T

Lana T

Zendesk Admin, Swotzy

Macha AI is a great addition. The knowledge base feature means our agents always have the right answers at their fingertips.

Mischa Wolf

Mischa Wolf

Head of Support, Topi

We're enjoying this integration so far. It's made our support team more efficient and our customers get faster responses.

Paula G

Paula G

Head of Customer Support, Xly Studio

The team enjoys using it. It saves considerable time on common questions and the integration options are excellent.

Kilian Leister

Kilian Leister

Support Head, Didriksons

Ready to supercharge your team with AI?

Get started in minutes. Connect your tools, configure your agents, and let AI handle the rest.

7-day free trial · no credit card required