n8n API Key Variable Scopes Tutorial: Least-Privilege Keys for Instance Variables

Introduction

A shared n8n instance usually has two different permission problems hiding inside one sentence: who may call the API, and which variables each workflow may read. An unscoped API key answers the first question with “everyone who holds this key may do everything,” which is the wrong answer for a deployment script, a monitoring job, or a contractor integration. This tutorial fixes that by giving each key only the variable scopes it needs, testing the key with curl before any real system depends on it, and separating key scopes from variable scopes so the two ideas stop getting confused.

This guide is for n8n admins and automation engineers on an Enterprise plan, or on a self-hosted Business or Enterprise edition, who manage a shared instance. It assumes you already run n8n and can sign in as an owner, admin, or global member with permission to create API keys.

Quick answer

On an Enterprise n8n instance, open Settings, then n8n API, create a key, and select only variable:list and variable:create for a deployment caller, then test it with curl against /api/v1/variables before using it anywhere else.

Evidence

The official authentication documentation states the design rule plainly: “Choose the minimum scopes needed for the key’s intended purpose.” That sentence is the whole tutorial in one line, and every step below is just a way to make it verifiable. The same page warns that non-Enterprise API keys have full access to all of the account’s resources and capabilities, so a scoped key is not a default, it is an Enterprise feature you must choose deliberately.

The variable side has its own hard limits, also from official documentation. Custom variables are available on n8n Cloud Pro and Enterprise plans, and on self-hosted Business and Enterprise editions, and only instance owners and admins can create variables through the interface. A variable key may be at most 50 characters long, its value at most 1000 characters, and both are limited to letters, numbers, and underscores. Project-scoped variables arrived in n8n 1.118.0, while earlier versions only supported global variables. A long JSON blob, a private key, or a value with dashes and dots does not fit, so check the format before designing around a variable.

The timing is also specific. The n8n 2.41.7 release, dated October 5, 2026, lists exactly one API fix: let global members grant variable scopes to API keys. That is a narrow fix, not a new feature for every plan, and it matters only if a global member creates keys for other people. If your instance is older than 2.41.7 and a global member cannot grant a variable scope, upgrade first instead of handing that member a broader key as a workaround.

Finally, the scope list itself is small, which is good news. The official API authentication reference lists exactly four variable scopes: variable:create, variable:list, variable:update, and variable:delete. There is no separate variable:read scope, so listing is the read path for variables through the API. Any design that asks for “read-only variable access” translates to exactly one scope: variable:list, and nothing else.

Prerequisites

  • An n8n instance on an Enterprise plan, or a self-hosted Business or Enterprise edition, because scoped API keys are an Enterprise feature.
  • An owner, admin, or global member account that can create API keys. On versions before 2.41.7, a global member may be unable to grant variable scopes, so use an owner or admin account, or upgrade first.
  • curl and jq installed on the machine you test from, so you can inspect API responses without pasting keys into a browser console.
  • A test variable name that is safe to create and delete, such as TOOLPILOT_SCOPE_TEST, and no production variable with the same key.
  • A secrets habit: store the new key in an environment variable or a vault for the test, never in a workflow, a chat message, or a committed file.

Step-by-step guide

Step 1: Decide the least-privilege scope set before opening Settings

Write down the caller’s job in one sentence, then map it to scopes. A deployment script that only provisions variables needs variable:list and variable:create. A read-only monitoring job needs variable:list only. A cleanup job needs variable:list and variable:delete, and it should never also carry variable:update unless it truly edits values. A key that also needs to read workflows is a different key design, not a reason to add workflow:list to the variable key.

Keep a one-line record for each key: label, owner, scopes, expiry, and the system that holds it. That record is what turns a later 403 into a five-minute fix instead of a guessing game.

Step 2: Create the scoped key

  1. Sign in to n8n.
  2. Go to Settings, then n8n API.
  3. Select Create an API key.
  4. Enter a label that names the caller and the job, for example deploy-variables-staging.
  5. Set an expiration time. A short expiry on a deployment key is a feature, not an annoyance, because it forces a rotation review.
  6. On an Enterprise instance, select only the scopes from Step 1. For the deployment example, select variable:list and variable:create, and clear everything else.
  7. Copy the key immediately. n8n shows the full key once, so store it in your vault now. If you lose it, delete the key and create a new one, because there is no “show again” path.

If you do not see a scopes picker at all, stop. Your plan does not support scoped keys, and the key you are about to create will have full access. Do not proceed as if it were scoped. Either upgrade the plan, or restrict the key by other means, such as a short expiry, a dedicated service account, and a network allowlist in front of the instance.

Step 3: Create a test variable with the right variable scope

Variable scopes are a property of the variable, not of the key, and the official custom variables documentation explains the two choices. A global variable is available to everyone on the instance, across all projects. A project-scoped variable is available only within the specific project it was created in, and when a project variable shares a key with a global variable, the project value takes precedence inside that project’s workflows.

  1. Open the Variables tab from the overview page or from a specific project.
  2. Select Add Variable.
  3. Enter a key such as TOOLPILOT_SCOPE_TEST and a harmless value such as scope-test.
  4. If you create from the overview page, choose the scope: Global for instance-wide configuration, or Project for one project’s configuration, and select the project.
  5. Select Save.

Use a global variable only when every project genuinely needs the same value. When in doubt, choose a project scope, because narrowing a variable later means auditing every workflow that already read the global value. Remember the format limits from the Evidence section: letters, numbers, and underscores only, at most 50 characters for the key and 1000 for the value.

Step 4: Prove the key can list variables, and nothing else

Test from a terminal, with the key in an environment variable, never typed into a shared transcript. Replace https://your-n8n-instance with your instance URL, and keep the /api/v1 path exactly as shown, because that is the public API root documented in the authentication guide.

export N8N_HOST="https://your-n8n-instance"
export N8N_API_KEY="paste-the-new-key-here"

curl -s "$N8N_HOST/api/v1/variables" \
  -H "X-N8N-API-KEY: $N8N_API_KEY" | jq .

Expect a 200 response with a data array that includes your test variable. That proves the key, the header name, and the base URL are correct.

Now run the negative test, which is the test most teams skip. Call an endpoint the key must not reach, such as the workflows list, and confirm it fails:

curl -s -o /dev/null -w "%{http_code}\n" "$N8N_HOST/api/v1/workflows?limit=1" \
  -H "X-N8N-API-KEY: $N8N_API_KEY"

Expect 403 for a variable-only key. A 200 here means the key is broader than you designed, so delete it and repeat Step 2. A scoped key that passes its positive test but fails its negative test is not a scoped key.

Step 5: Prove the key can create a variable through the API

With a key that carries variable:create, create a second test variable from the terminal:

curl -s -X POST "$N8N_HOST/api/v1/variables" \
  -H "X-N8N-API-KEY: $N8N_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key": "TOOLPILOT_API_CREATED", "value": "api-created"}' | jq .

Expect a 200 or 201 response describing the new variable, including its id. Save that id, because you need it for cleanup. If your version’s API playground shows extra fields for the create call, check the playground at /api/v1/docs on a self-hosted instance before adding fields you guessed, because guessed fields are how a working call turns into a confusing 400.

Then confirm the new variable appears in the list call from Step 4. If it does not, check whether you created it in a different project scope than the one you listed.

Step 6: Use the variable in a workflow, read-only

Custom variables are read-only inside workflows, which is a safety property, not a limitation to work around. In a Code node or an expression, read the value with $vars:

const endpoint = $vars.TOOLPILOT_SCOPE_TEST;
return [{ json: { endpoint } }];

A workflow that needs to update its own state at runtime should not write back into a custom variable. Use workflow static data for that case, as the official variables documentation directs, and keep custom variables for configuration that a human or a scoped API caller changes deliberately.

If the workflow runs but the value comes back empty, do not assume the API is broken. An empty result usually means the variable has no value, the key is spelled differently, or a project variable with the same key is overriding the global value inside that project. Check the Variables tab for that project first, because precedence is documented behavior: the project value wins inside its own project.

Step 7: Clean up, rotate, and document the key

Delete both test variables when the tests pass, through the API with a key that carries variable:delete, using the id from the create call, or from the Variables tab. Then revoke a tutorial-only test key from Settings, then n8n API. For a production key, rotate in this order: create the replacement key, update the caller, verify it with the Step 4 tests, and only then delete the old key.

For the bigger picture on keeping a shared instance safe, read our complete n8n guide, which maps installation, security patching, and scaling in the order you will actually need them. When a value truly is a secret rather than configuration, follow our n8n external secrets tutorial instead of putting it in a variable, and if a workflow cannot read an environment value at all, the Code node environment variable fix explains which of the three security settings is blocking it.

Troubleshooting

The scopes picker is missing when creating a key

This is a plan signal, not a UI bug. Scoped keys are an Enterprise feature, and the public API is not available during a free trial. A key created without a scopes picker has full access, so treat it accordingly: give it a short expiry, a narrow purpose, and a dedicated holder. Do not label it “scoped” in your records, because the next person to read that label will trust a restriction that does not exist.

A global member cannot grant variable scopes

Upgrade to n8n 2.41.7 or later. That release fixed exactly this case: global members can grant variable scopes to API keys. Before the fix, the workaround was to have an owner or admin create the key, which is still a valid fallback on an older version, but it should not become permanent, because it concentrates key creation on one person and hides the real permission gap.

The API returns 403 with a valid key

Read the scope first. A 403 on a valid key means the key lacks the scope for that resource and action, and the community symptom for the same class of problem is the message “User is missing a scope required to perform this action.” Check three things in order: the key label in Settings, then n8n API, to confirm the scopes you actually saved; the endpoint you called, to confirm it matches a scope the key has; and the instance version, if a global member created the key before 2.41.7. Never fix a 403 by replacing a scoped key with an unscoped one in production, because that turns a permission error into a permanent over-privilege.

The API returns 401, or the key cannot be found

A 401 usually means the header, the key value, or the instance URL is wrong, not that the scopes are wrong. Confirm the header is exactly X-N8N-API-KEY, confirm the base URL ends in /api/v1 with no extra path segment, and confirm you copied the full key when it was shown once. If the key was deleted or expired, the fix is a new key, not a retry, because n8n never shows a key again after creation.

A variable value is wrong inside one project but right everywhere else

That is project precedence working as documented. A project-scoped variable with the same key as a global variable overrides the global value inside that project. Open the Variables tab for that project, find the overriding key, and either correct its value or delete the project variable so the global value applies again. Do not “fix” this by editing the global value, because that changes every other project that reads it.

A variable create call fails on the key or the value

Check the format limits before anything else: the key may be at most 50 characters, the value at most 1000, and both may contain only letters, numbers, and underscores. A key with a dash, a dot, or a space fails, and a long JSON string fails on length. Shorten the key, move structured data into a workflow or a data table, and keep variables for short configuration values they were designed to hold.

FAQ

The FAQ entries above answer the questions readers ask most. Read them before designing a key, because most scope mistakes are design mistakes, not typing mistakes.

Conclusion

A scoped n8n API key is a small object with a large blast radius, and the discipline around it is simple: one caller, one job, the minimum variable scopes, a positive test, a negative test, and a rotation date. Separate the key scope from the variable scope, keep secrets in credentials instead of variables, and upgrade to 2.41.7 or later if a global member needs to grant variable scopes. Then a leaked key causes bounded damage by design, instead of damage discovered by accident.

Frequently asked questions

Are API key scopes the same as variable scopes?

No. An API key scope such as variable:list controls what one API key may do through the public API. A variable scope such as Global or Project controls which workflows can read that variable. You need both concepts to design least-privilege access: the key scope limits the caller, and the variable scope limits the audience.

Do I need an Enterprise plan to use variable scopes on an API key?

Yes, for scoped keys. n8n documents that scope selection at key creation is an Enterprise feature, and that non-Enterprise API keys have full access to all of the account resources and capabilities. If you do not see a scopes picker, your plan does not support scoped keys, and you should treat that key as fully privileged.

What changed for global members in n8n 2.41.7?

Version 2.41.7, released on October 5, 2026, fixed API permissions so global members can grant variable scopes to API keys. Before that fix, a global member could be blocked from granting those scopes even when the task legitimately needed them. Upgrade to 2.41.7 or later if a global member hits that specific limitation.

Can a workflow change a custom variable at runtime?

No. Custom variables are read-only inside workflows. You read them with $vars in the Code node or in expressions, and you change them through the Variables tab in the interface or through the API with a key that carries the right variable scope. For data a workflow itself must update, use workflow static data instead.

Should I store secrets in n8n variables?

No. Variables hold reusable configuration values, not secrets. Put passwords, tokens, and private keys in n8n credentials, or in an external secrets vault, and reference them only where credentials are allowed. A variable value that a workflow can read is not a substitute for a credential.

What should I do when a scoped key returns 403?

Stop and read the scope, not the key. A 403 on an otherwise valid key almost always means the key lacks the scope for that resource and action, for example calling the workflows list endpoint with a key that only has variable:list. Create a new key with the missing scope, or narrow the caller to the endpoints its scopes already allow, and retest.

TP
ToolPilot Team

We install, break, and fix automation tools so you don't have to. Every tutorial on ToolPilot is tested hands-on before publishing.

Keep reading