How to have dynamic header value

I have the following flow

The idea is I generate a workflow api key that I send to a BE, and the BE reply with x-api-key in the header in order to continue the process.

The issue is, I setup this header

That from an exemple I found online it should work, yet it doesnt.

If I put a static value it work ofc, but the goal is to have dynamic one.

Is this something possible in n8n or not ?

Thank you

It looks like you are changing the actual account, you need to pass the variable inside the “Call JOB/CEP Analysis“ node.

image

after enabling this option you should be abble to pass the x-api-key as a header.

And about the Authentication you should set it to None and let the header handle the auth.

1 Like

I have it set as follows and works as expected:

{{ $(activity-name).json.access_token }}

Thank you for your reply. I think I explained poorly.

The issue is not really sending the header from the HTTP node, this is ok. The issue is, inside the wait webhook callback, I am expecting the Header back from my webservice, but currently the value there can’t be dynamic.

If my webhook callback have auth header where I set a static x-api-key that I send from the HTTP node to my webservice, then when the webservice reply with the key, the webhook node resume progress correctly. But if instead I use the dynamically generate key, pass it to the webservice with the HTTP node, with the dynamic node I set above the webhook will be pending forever and never resume progress cause the header is never correct.

And about the Authentication you should set it to None and let the header handle the auth.
If I set my webhook auth to none, it will work but then it wont really check the x-api-key provided right ?

I want to clarify the real issue here, because in my opinion this is not about whether the HTTP Request node can send header, that part works fine.

The problem is how the Wait node validates authentication on resume.


The real issue

When using a Wait node with “Resume via Webhook” and incomingAuthentication = headerAuth:

  • The Wait node only supports static header values

  • It does NOT evaluate expressions per execution

  • Dynamic secrets (like a per-run x-api-key) will never match

  • Result: the workflow stays pending forever

This explains the behavior exactly:

Scenario Result
Static x-api-key :slight_smile: resumes
Dynamic x-api-key :frowning: pending forever

This is by design, not a bug.


Suggested solution

  • Set the Wait node authentication to None
  • Resume the workflow normally
  • Immediately validate the dynamic key yourself in a Code node

The resume URL is already a high-entropy, execution-scoped secret.
The header is an additional guard, but must be validated manually.

Here’s an example. Please note this is for proof of concept only as I have no way of testing this beyond syntax:

Place this node immediately after the Wait node
Mode: Run once for each item

// ============================================================================
// CALLBACK AUTH VALIDATION
// MODE: Run once for each item
// PURPOSE:
// - Validate dynamic x-api-key returned via Wait webhook callback
// - Enforce per-execution auth (Wait node auth is static-only)
// ============================================================================

// -------------------- INPUT --------------------
const item = $json;

// Webhook resume metadata (shape varies slightly by version)
const headers =
item.headers ||
item.webhookHeaders ||
item.request?.headers ||
{};

// Case-insensitive header lookup
function getHeader(headers, name) {
const key = Object.keys(headers).find(
k => k.toLowerCase() === name.toLowerCase()
);
return key ? headers[key] : undefined;
}

// -------------------- EXPECTED KEY --------------------
const expectedKey = item.xApiKey;
if (!expectedKey) {
throw new Error(“Missing expected xApiKey in execution context.”);
}

// -------------------- RECEIVED KEY --------------------
const receivedKey = getHeader(headers, “x-api-key”);
if (!receivedKey) {
throw new Error(“Missing x-api-key header in callback request.”);
}

// -------------------- VALIDATION --------------------
if (receivedKey !== expectedKey) {
throw new Error(“Callback authentication failed: x-api-key mismatch.”);
}

// -------------------- SUCCESS --------------------
return item;

Why this should work:

  1. Wait node auth is static only
  2. Expressions are not evaluated at resume time
  3. This pattern gives you:
    1. per-execution secrets
    2. deterministic behavior
    3. full control over failure handling

Alternatives

  1. Put the key in the callback URL as a query param
  2. Use a single static shared secret (if acceptable)
  3. Use manual validation + logging instead of throwing

If anyone has found a cleaner native approach, I’d genuinely like to learn, but as of now, this is the only reliable pattern I know of.

1 Like

Hi thanks, yeah with code it would work, I was wondering a full auth header solution in the http directly. I guess not possible then thank you !