Fix 5 API Key Not Recognized Errors in n8n

n8n API key not recognized 401 fix guide

Complete fix guide for every n8n API key not recognized and 401 Unauthorized error

 


 

You generated the key, copied it carefully, pasted it into the header and n8n still throws 401. Most developers spend 40 minutes re-checking the key itself. The key is almost never the problem. The problem is where the key gets lost between your client and n8n’s auth middleware a trailing space, a proxy that strips custom headers, a container that never reloaded the .env, or an endpoint that simply doesn’t accept API key auth. This guide covers every scenario, with real error logs and the exact fix for each one.

 

 

Who this is for: Developers and DevOps engineers who integrate with a self‑hosted or n8n Cloud instance via its REST API. We cover this in detail in the n8n Authentication Errors Guide. If you receive “API key not recognized” from n8n, the request is missing a valid x-n8n-api-key header or the key stored in the environment variable is wrong.

 


Start Here: Debug Decision Tree

Most devs get stuck because they assume all 401 errors are the same. They’re not. Find your exact branch below — each path leads to the right section so you don’t waste time chasing the wrong fix.

You’re getting 401 “API key not recognized” – answer these questions:

Q1. Are you calling n8n’s OWN REST API (not an external service)?
→ YES → Q2 ↓
→ NO (OpenAI, ElevenLabs, etc. failing INSIDE n8n) → Jump to Section A

Q2. Does the exact same curl command work when hitting port 5678 directly?
→ YES (works direct, fails via domain/proxy) → Jump to Section 5 — Reverse Proxy
→ NO (fails even direct) → Q3 ↓

Q3. Did you restart n8n after setting the API key in .env?
→ NO → Restart the container, retry. Done.
→ YES → Q4 ↓

Q4. Are you calling /rest/workflows or /api/v1/workflows?
/rest/ with x-n8n-api-key → Jump to Section B — Wrong Endpoint
/api/v1/ with x-n8n-api-key → correct, go to Q5 ↓

Q5. Does the credential test show green in the UI but workflows still fail?
→ YES → Jump to Section C — Credential Test Passes but Execution Fails
→ NO → Q6 ↓

Q6. Did this start happening after a Docker restart, n8n update, or migration?
→ YES → Jump to Section D — Encryption Key Mismatch
→ NO → Work through Sections 1–4 in order (header, whitespace, key value)


Quick fix

  1. Verify the exact API key in Settings → API → API Key (or the .env file).
  2. Ensure the request header is spelled x-n8n-api-key (case‑insensitive) and contains no extra spaces or line‑breaks.
  3. Restart n8n after any change to the .env file.

After these three steps the error should disappear.


1. Why n8n Returns “API key not recognized”

If you encounter any invalid credentials error resolve them before continuing with the setup.

Root Cause How n8n Detects It
Missing header req.headers['x-n8n-api-key'] is undefined
Wrong header name Header key does not match x-n8n-api-key (e.g., api-key)
Incorrect key value Header value ≠ process.env.N8N_API_KEY
Trailing/leading whitespace No String.trim() before comparison
Key not loaded .env not re‑loaded after edit
Multiple API keys (Enterprise) Request uses a key not assigned to the calling user

Typical symptom for all cases: 401 Unauthorized with message “API key not recognized”.

Understanding the exact cause lets you target the right fix without chasing dead‑ends.


2. Locate the Correct API Key in n8n

If you encounter any token expired error resolve them before continuing with the setup.

Self‑hosted (Docker / Binary)

# Show the key stored in the .env file (default location)
cat /home/n8n/.n8n/.env | grep N8N_API_KEY

If the variable is missing, generate a new one:

# Generate a 32‑byte hex string
openssl rand -hex 32
# Append it to the .env file
echo "N8N_API_KEY=9f2c3d4e5b6a7c8d9e0f1a2b3c4d5e6f" >> /home/n8n/.n8n/.env

n8n Cloud

  1. Open Settings → API → API Key in the UI.
  2. Click Copy; the key lives in the cloud’s secret manager (you can only regenerate, not view again).

EEFA note: Never commit the API key to source control. Use secret‑management tools (Docker secrets, Kubernetes Secret, or .env files excluded via .gitignore).


3. Correctly Send the API Key in Your Request

3.1 cURL Example

curl -X GET "https://your-n8n-instance.com/rest/workflows" \
     -H "x-n8n-api-key: 9f2c3d4e5b6a7c8d9e0f1a2b3c4d5e6f" \
     -H "Accept: application/json"

Common pitfalls – see the table below.

Pitfall Symptom Fix
Double quotes around the key with trailing space 401 error Trim spaces: x-n8n-api-key:$(echo -n "$KEY" | tr -d ' ')
Using Authorization: Bearer <key> 401 error Switch to x-n8n-api-key.
Sending key in query string (?api_key=) 401 error n8n only reads the header; move it to header.

3.2 JavaScript (Node.js) Example

require('dotenv').config();          // Load .env
const fetch = require('node-fetch');

const API_URL = 'https://your-n8n-instance.com/rest/workflows';
const API_KEY = process.env.N8N_API_KEY.trim(); // Trim whitespace

Next, perform the request and handle errors:

(async () => {
  const res = await fetch(API_URL, {
    method: 'GET',
    headers: {
      'x-n8n-api-key': API_KEY,
      'Accept': 'application/json',
    },
  });

  if (!res.ok) {
    const err = await res.text();
    throw new Error(`Request failed (${res.status}): ${err}`);
  }

  const data = await res.json();
  console.log(data);
})();

EEFA tip: In production, wrap the request in a retry block and log the raw request/response without the API key (mask it) to avoid leaking credentials.


4. Step‑by‑Step Troubleshooting Checklist

Step Action Verification
1 Confirm the key value – open .env or UI and copy it verbatim. echo $N8N_API_KEY matches the UI copy.
2 Check header spelling – must be exactly x-n8n-api-key. curl -v shows > x-n8n-api-key: line.
3 Trim whitespace – add .trim() in code or use sed 's/ *$//'. No trailing spaces in logs (| delimiters).
4 Reload environment – restart Docker container or pm2 restart n8n. docker logs n8n | grep API_KEY shows new value.
5 Test with cURL – bypass your app to isolate the issue. Successful JSON response.
6 Inspect n8n logs – look for API key not recognized lines. Log timestamp matches request.
7 Validate against multiple keys (Enterprise) – ensure the key belongs to the user. Use the UI to view assigned keys.
8 Check reverse proxy – ensure it forwards the x-n8n-api-key header (some proxies strip unknown headers). Add proxy_set_header x-n8n-api-key $http_x_n8n_api_key; in Nginx config.

If any step fails, correct the issue before moving to the next.


5. Reverse Proxy Gotchas

Many production deployments sit behind NGINX or Traefik. By default, these proxies may drop custom headers.

NGINX Example

location / {
    proxy_pass http://localhost:5678;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    # Preserve the API key header
    proxy_set_header x-n8n-api-key $http_x_n8n_api_key;
}

Traefik (Docker) Example

labels:
  - "traefik.http.middlewares.n8n-headers.headers.customrequestheaders.x-n8n-api-key=YOUR_KEY"
  - "traefik.http.routers.n8n.middlewares=n8n-headers"

EEFA warning: Hard‑coding the key in proxy config defeats the purpose of secret rotation. Prefer forwarding the original header instead of injecting a static value.


6. Regenerating a Lost or Compromised API Key

  1. Self‑hosted – edit .env and replace N8N_API_KEY with a newly generated value (see Section 2).
  2. n8n Cloud – go to Settings → API → Regenerate; all existing clients must be updated instantly.

Production tip: Deploy a rolling key rotation script that updates the key, notifies dependent services via a webhook, and restarts containers one at a time to avoid downtime.


7. When “API key not recognized” Persists After Fixes

Symptom Likely Hidden Cause Remedy
401 error despite correct header Proxy stripping header (see Section 5) Verify curl -v through the proxy; add proxy_set_header.
401 error only for certain IPs IP‑based firewall blocking header Whitelist the client IP or disable the rule.
401 error after Docker compose up .env file not mounted (volume missing) Add volumes: - ./n8n/.env:/home/node/.n8n/.env.
401 error in CI pipeline CI secret variable not exported Echo the variable in the CI step to confirm; use export N8N_API_KEY=....

 


Section A: External API Keys Failing Inside n8n Workflows (OpenAI, ElevenLabs, fal.ai, Pinecone)

This is the most common real-world version of this error in 2025 — and it’s completely different from n8n’s own API key. You’re not calling n8n; you’re calling an external service from inside an n8n workflow, and that service returns 401. Here’s what the error looks like in the n8n execution log:

{
  "errorMessage": "Authorization failed - please check your credentials",
  "errorDescription": "Request failed with status code 401",
  "errorDetails": {
    "rawErrorMessage": ["401 - \"{\\\"message\\\":\\\"Invalid API key\\\",\\\"statusCode\\\":401}\""],
    "httpCode": "401"
  },
  "n8nDetails": {
    "nodeName": "HTTP Request",
    "nodeType": "n8n-nodes-base.httpRequest",
    "n8nVersion": "1.108.1 (Self Hosted)"
  }
}

If this is your error, the x-n8n-api-key header is irrelevant. The problem is how n8n is sending the external service’s credentials. Work through these fixes in order:

 


 

A1. API key works in Postman/curl but fails inside n8n

This is the single most-reported pattern across the n8n community. The key is valid — n8n is sending it wrong. Three causes in order of likelihood:

Hidden characters from copy-paste. When you paste an API key into n8n’s credential field from a browser, an email, or a PDF, invisible Unicode characters (zero-width spaces, non-breaking spaces) tag along. The credential test endpoint is sometimes more lenient than the actual API call — so it passes the test but fails on execution.

Fix: delete the key from the credential field entirely, then type the key manually or paste it into a plain text editor first to strip invisible characters, then copy from there into n8n.

Wrong authentication method selected. In the HTTP Request node, the “Authentication” dropdown matters. If the API expects Authorization: Bearer sk-xxx but you’ve selected “Header Auth” with key name Authorization and value sk-xxx (without the word “Bearer”), it fails. The correct value would be Bearer sk-xxx.

Using a dedicated node vs. HTTP Request node. n8n’s dedicated OpenAI node, ElevenLabs node, etc. use their own authentication logic separate from the HTTP Request node. If one fails, try the other to isolate whether it’s a credential problem or a node implementation problem.


A2. OpenAI sk-proj-… project-scoped keys not recognized

OpenAI introduced project-scoped API keys (format: sk-proj-...) which require an additional OpenAI-Project header. n8n’s built-in OpenAI node does not fully support this format as of mid-2025. The result:

Authorization failed - please check your credentials
Missing bearer or basic authentication in header

Fix option 1 (recommended): Use a classic user API key (sk-...) instead of a project key. In the OpenAI dashboard, go to API keys → create a new key without selecting a project.

Fix option 2: Use the HTTP Request node instead of the dedicated OpenAI node and pass both required headers manually:

Authorization: Bearer sk-proj-YOUR_KEY
OpenAI-Project: proj_YOUR_PROJECT_ID
Content-Type: application/json


A3. Credential test shows green but execution returns 401

This is the most confusing pattern — the credential test passes, your curl works, but the actual workflow execution returns 401. Reported across ElevenLabs, OpenRouter, fal.ai, and OpenAI nodes.

Why it happens: n8n’s credential test endpoint hits a simple “ping” endpoint of the external API (often just a GET to check if the key exists). The actual operation (e.g., text-to-speech, image generation) hits a different endpoint that may have scope restrictions, usage tier limits, or require a different auth header format.

Fix sequence:

  1. Delete the existing credential in n8n completely.
  2. Create a brand new credential from scratch — do not copy-paste from the old one.
  3. Test by running the specific operation that was failing (not just the credential test).
  4. If it still fails, test the exact same API call via curl with the same key to confirm the key has access to that specific operation/endpoint.
  5. Check the external service’s dashboard — some APIs (ElevenLabs free tier, fal.ai) disable specific operations based on plan tier, which returns 401 even with a valid key.
# Test ElevenLabs text-to-speech directly
curl -X POST https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM \
  -H "xi-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "test", "model_id": "eleven_monolingual_v1"}'
# If this returns 401, the issue is with your key/plan, not n8n

Section B: Wrong Endpoint – /rest/ vs /api/v1/ Confusion

This catches a huge number of developers. n8n has two distinct API route structures and they behave differently with API key authentication:

Endpoint prefix Purpose Auth method API key works?
/api/v1/ Public REST API (workflows, executions, credentials) x-n8n-api-key header ✅ Yes
/rest/ Internal editor API (used by the n8n UI itself) Session cookie / browser auth ❌ No – returns 401

The /rest/ endpoints are what n8n’s own browser UI uses. They require session-based authentication, not API key headers. If you’re hitting /rest/workflows with your API key, you’ll always get 401 regardless of how correct your key is.

Fix – use the correct public API path:

# WRONG — internal endpoint, API key doesn't work here
curl -H "x-n8n-api-key: YOUR_KEY" http://localhost:5678/rest/workflows

# CORRECT — public API endpoint
curl -H "x-n8n-api-key: YOUR_KEY" http://localhost:5678/api/v1/workflows

For self-referencing n8n API credentials (when n8n calls its own API inside a workflow): the Base URL must be your n8n instance’s external URL, not localhost – because n8n inside Docker doesn’t reach itself via localhost. Use the container name or external domain:

# If n8n is in Docker, use the container name or service name from docker-compose
Base URL: http://n8n:5678/api/v1
# NOT: http://localhost:5678/api/v1  ← this resolves inside the container, not to n8n

Section C: JWT Timestamp Bug – Fresh API Key Returns 401 Immediately

This one is genuinely surprising. You generate a brand new API key from the n8n UI, use it immediately — and get 401. You’ve verified the header, the endpoint, everything. The key is completely fresh. It still fails.

n8n API keys are JWT tokens. A confirmed bug (reported October 2025, GitHub issue #21054) causes the JWT’s iat (issued-at) timestamp to be set to a future timestamp — typically 6–7 minutes ahead of the actual current time. JWT validation rejects tokens whose iat is in the future, because it means “this token hasn’t been issued yet.” The result is a 401 that has nothing to do with your key value.

# Decode your API key (it starts with eyJ...) to check the iat field
echo "YOUR_JWT_API_KEY" | cut -d'.' -f2 | base64 -d 2>/dev/null | python3 -m json.tool
# Look for: "iat": 1761135964
# Convert to human time: date -d @1761135964
# If iat is in the future, you've hit this bug

Fix 1: wait 10 minutes. Once the server clock catches up to the iat timestamp, the key becomes valid automatically. This is the easiest workaround.

Fix 2: sync the container clock. The root cause is clock drift between the Docker container and the host. Fix it:

# Check time inside the n8n container
docker exec -it n8n date

# If it differs from host time, sync the host NTP
sudo timedatectl set-ntp true
# Then restart the container
docker restart n8n

Fix 3: regenerate the key after the clock is synced. The existing key’s iat is baked in — you must generate a new key after fixing the clock drift for the timestamp to be correct.


Section D: N8N_ENCRYPTION_KEY Mismatch: Credentials Silently Break After Update or Restart

This is the highest-impact, least-documented cause of “API key not recognized” in production. After a Docker container rebuild, an n8n version update, or a server migration, every stored credential silently stops working. The error in the execution log looks identical to a wrong API key:

Authorization failed - please check your credentials
# or
Credentials could not be decrypted.
The likely reason is that a different 'encryptionKey' was used to encrypt the data.

What’s happening: n8n encrypts all stored credentials (API keys, passwords, OAuth tokens) using a key defined by N8N_ENCRYPTION_KEY. On first launch, if you don’t set this variable explicitly, n8n generates a random key and saves it to ~/.n8n/config. If that file disappears — because you rebuilt the Docker volume, migrated servers, or forgot to persist the .n8n directory — n8n generates a new random key. It can no longer decrypt the credentials stored with the old key. Every workflow that touches any credential will return 401 or “credentials could not be decrypted.”

How to prevent this? (do this before it happens)

# Generate a stable encryption key and save it NOW
openssl rand -hex 32
# Add to your .env file
N8N_ENCRYPTION_KEY=your_generated_64_char_hex_string

# In docker-compose.yml, set it explicitly
environment:
  - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}

How to recover if it already happened?

  1. Find the old encryption key. Check ~/.n8n/config on the original host — it’s stored there as "encryptionKey": "...". If you have a backup of the .n8n directory, extract it from there.
  2. Set that exact key as N8N_ENCRYPTION_KEY in your environment and restart n8n.
  3. If the old key is completely lost, there is no way to decrypt the stored credentials. You must recreate all credentials from scratch.
# Find the encryption key from a running container's config
docker exec -it n8n cat /home/node/.n8n/config | grep encryptionKey

# Or from a backed-up .n8n directory
grep encryptionKey /path/to/backup/.n8n/config

EEFA note: In queue mode (multiple n8n workers), every worker and the main instance must load the identical N8N_ENCRYPTION_KEY value. If even one worker has a different key, credentials will silently fail on that worker’s executions but work fine on others — making this extremely hard to diagnose.


Section E: Reading Real n8n Logs to Diagnose API Key Errors

Most developers check the n8n UI execution error and stop there. The real diagnostic information is in the container logs. Here’s how to read them and what to look for:

Enable verbose logging

# Add to your .env or docker-compose environment
N8N_LOG_LEVEL=debug

# Tail live logs
docker logs -f n8n 2>&1 | grep -i "api\|auth\|401\|key\|credential"

What each log pattern means?

Log line What it means Fix
API key not recognized Header received but value doesn’t match stored key Sections 1–4: verify key value, whitespace, reload env
Unauthorized with no additional message Header is missing entirely — never reached auth middleware Section 5: proxy stripping header, or wrong endpoint (Section B)
Credentials could not be decrypted Encryption key mismatch after restart/migration Section D: recover or reset N8N_ENCRYPTION_KEY
Request failed with status code 401 inside a workflow node External API rejecting the credential n8n is sending Section A: hidden characters, wrong auth method, plan limits
iat set to future timestamp or token rejected immediately JWT clock drift bug Section C: sync container clock, wait 10 min, regenerate key

Section F: Verify the Fix: Confirm Your API Key Is Working

After applying any fix, don’t assume it worked – verify it with a direct test before updating your application code.

Minimal verification curl

# Replace with your actual instance URL and key
curl -s -o /dev/null -w "%{http_code}" \
  -H "x-n8n-api-key: YOUR_KEY" \
  https://your-n8n-instance.com/api/v1/workflows

# Expected output: 200
# If you see 401: key is wrong or not loaded
# If you see 404: you're hitting the wrong endpoint path

Verbose debug to see exactly what’s being sent

curl -v \
  -H "x-n8n-api-key: YOUR_KEY" \
  https://your-n8n-instance.com/api/v1/workflows 2>&1 | grep -E "^[><]"

# Look for this line in output:
# > x-n8n-api-key: YOUR_KEY
# If that line is missing, your client isn't sending the header at all

Test through the proxy specifically

# Test DIRECT (bypassing proxy)
curl -H "x-n8n-api-key: YOUR_KEY" http://localhost:5678/api/v1/workflows

# Test VIA PROXY (through your domain)
curl -H "x-n8n-api-key: YOUR_KEY" https://n8n.yourdomain.com/api/v1/workflows

# If direct works but proxy fails → Section 5 (proxy stripping header)

9. Next Steps

  • Securely store API keys – explore Vault, AWS Secrets Manager, or Docker secrets.
  • Implement request retries with exponential back‑off for transient 401 errors.
  • Monitor authentication failures via Grafana or Prometheus alerts.

Conclusion

The “API key not recognized” error is almost always a mismatch between the key stored in n8n and the header sent by the client. By verifying the exact key, ensuring the x-n8n-api-key header is correctly spelled and whitespace‑free, and restarting the service after any environment change, the issue disappears. Remember to forward the header through any reverse proxy and keep keys out of source control. Following the checklist and the proxy‑preservation tips guarantees reliable, production‑grade API access to n8n.

Leave a Comment

Your email address will not be published. Required fields are marked *