What do common API errors mean?
A reference for HTTP status codes you might encounter when calling the Nozzle API, and how to fix them.
This guide explains the HTTP status codes you might see when calling the Nozzle API, what causes each one, and how to fix it.
For the basics of authenticating with the API and finding your IDs, see How do I authenticate with the Nozzle API?
Quick reference
| Status | Meaning | Most common cause |
|---|---|---|
400 Bad Request |
The request was malformed | Missing required field, invalid localeId, malformed JSON |
401 Unauthorized |
Authentication failed | Missing or malformed Authorization header |
403 Forbidden |
Authenticated, but no access to this resource | Wrong workspaceId, or rate limiting |
404 Not Found |
The requested resource doesn't exist | Wrong ID, deleted resource, typo in URL |
409 Conflict |
The request conflicts with current state | Stale versionId on PUT, or in-progress operation |
429 Too Many Requests |
Rate limit hit | Too many requests in a short window |
500–504 |
Server error | Transient infrastructure issue — usually retryable |
400 Bad Request
The server understood your request but rejected it because something in the body or URL is invalid.
Common causes:
- Missing a required field in the request body (e.g., a
PUT /keywordSources/{id}withoutversionId) - A
localeId,brandId, or other reference that doesn't exist in your workspace - Malformed JSON — a missing comma, unclosed bracket, or trailing comma in the request body
- A
(criteria_id, language)combination that doesn't have alocaleIdin Nozzle's catalog yet (see How do Nozzle locales work?) - Invalid
rrulestring in a schedule
How to fix:
- Validate the JSON body before sending — most languages have a built-in JSON parser that'll catch syntax errors
- Compare your request body against a known-good example (e.g., the
PUTexample in How do keyword sources work?) - If the response includes an error message, read it carefully — it usually points at the offending field
401 Unauthorized
The server couldn't authenticate your request. The API key is missing, malformed, or wrong.
Common causes:
- Missing the
Authorizationheader entirely - Header format is wrong — should be
Authorization: Token <your_api_key>(note the word "Token" and the space before the key) - Using a Bearer JWT that's expired (those expire roughly hourly and shouldn't be used for automation — see the auth guide)
- Pasting a key that has extra whitespace or got truncated
How to fix:
- Verify the header format exactly:
Authorization: Token <your_api_key> - Check that your environment variable or secrets store has the full key (no truncation, no trailing newline)
- If you're testing with a Bearer token from Chrome DevTools, switch to a permanent
TokenAPI key — Bearer tokens expire fast - Need a new key? Contact us
403 Forbidden
Your authentication is valid, but you don't have permission to access this specific resource.
Common causes:
- The
workspaceIdin your request doesn't match the workspace your API key was issued for - You're trying to access a project (
teamId) or keyword source (keywordSourceId) that lives in a different workspace - Transient rate limiting — under heavy load, some Nozzle endpoints return
403instead of429
How to fix:
- Verify the
workspaceIdin your request matches the one your API key was scoped to - Confirm the
teamIdandkeywordSourceIdbelong to that workspace (cross-workspace IDs aren't valid) - If you're hitting frequent
403s under heavy load, back off and retry with exponential backoff. If it persists, reach out
404 Not Found
The resource you asked for doesn't exist — or at least, not at the ID you provided.
Common causes:
- Typo in the ID (Nozzle IDs are 13–15 digits, easy to misread)
- The resource has been deleted (check
deletedAtif you have a recent copy) - You're using an ID from a different workspace
- Typo in the URL path (
keywordSourcevskeywordSources, missing trailing slash, etc.)
How to fix:
- Double-check the ID against the URL of the resource in app.nozzle.io
- List the parent resource to confirm the child still exists (e.g.,
GET /teamsto confirm ateamId, then list keyword sources for that team) - Check for extra path segments or missing query parameters in your URL
409 Conflict
Your request conflicts with the current state of the resource. The server is refusing to apply the change to prevent data loss or inconsistency.
On PUT /keywordSources/{id}
The most common 409 scenario. It usually means the versionId in your request body doesn't match the current version stored on the server — someone (or some other process) modified the keyword source between your last GET and your PUT.
How to fix:
- Re-GET the keyword source to fetch the current state and the new
versionId - Re-apply your intended change to the fresh copy
- PUT again with the new
versionId - Don't blindly increment or guess the
versionId— it's a save timestamp, and forging it defeats the purpose of the conflict check
For more on the versioning model, see the keyword sources guide.
On DELETE requests
409 Conflict on DELETE usually means the resource is in a state that prevents deletion — for example, an in-progress operation, a dependent resource that needs to be removed first, or a transient lock.
How to fix:
- Wait briefly and retry (transient locks usually clear within seconds)
- Verify there are no dependent resources (e.g., a project may need its keyword sources removed before it can be deleted)
- If you're seeing repeated
409s on bulk deletes, reach out — we can often help clean up server-side faster than retrying
429 Too Many Requests
You've sent too many requests in a short window and have hit a rate limit.
How to fix:
- Implement exponential backoff — wait, retry, wait longer if it fails again
- Batch requests where possible (e.g., update many phrases in a single PUT instead of calling PUT once per phrase)
- If your integration legitimately needs higher throughput, contact us to discuss your use case
500–504 Server errors
Something went wrong on Nozzle's end. These are usually transient.
How to fix:
- Retry the request after a short delay (usually a few seconds is enough)
- If a request consistently returns
500or higher across multiple retries, the request itself may be triggering a server bug — contact us with the request details (URL, body, time of request) so we can investigate - Build retry logic into any production integration — transient server errors happen with any API
It worked, but the result wasn't what I expected
Not all problems show up as error codes. A few patterns to watch for:
- A
PUTseems to have created a new keyword source instead of updating the existing one. Check that you sent the sameidand a currentversionIdin the request body. If the keyword source was modified between your GET and your PUT, you may need to re-fetch and retry. - Phrases I expected to be removed are still tracked. Remember that
PUT /keywordSources/{id}requires the full object — if you sent a partial body, missing fields may have been preserved as-is rather than removed. Always GET the full object, modify it, and PUT it back. - Devices or locales seem to have been multiplied unexpectedly. In a
basickeyword source, every phrase is tracked against every locale and device. If you have 10 phrases × 4 locales × 2 devices, you'll get 80 keyword combinations. For per-phrase targeting, use ajsonkeyword source.
Need help?
If you're hitting an error that isn't covered here — or one that's covered here but isn't behaving the way the doc describes — reach out with the request URL, request body (redact your API key), and the response status and body. We'd rather work through it with you than have you stuck.