Archived docs Get your API Key
Get started
Tutorials
Guides
Reference
Help for coding agents
πŸ€– AI Assistant

n8n HTTP Request node

Most n8n tutorials and shared workflows call JSON2Video with n8n's built-in HTTP Request node: one node sends the movie to POST /v2/movies, a Wait node pauses, and a second HTTP Request node checks the status until the video is ready. This page explains that setup, how to put n8n values in the JSON body, and how to fix the errors people hit most.

Use this page if:

  • you are following a tutorial or imported a workflow that already has HTTP Request nodes, or
  • you are on self-hosted n8n without community nodes.

Building a new workflow from scratch on n8n Cloud or a recent self-hosted version? The official JSON2Video node is simpler: the key goes in a credential, template variables show up as fields, and Render and Wait does the polling for you.

This video uses the Quick start in the dashboard; the steps are the same.

Video: render a video with n8n's HTTP Request node (2:55) Β· Open the video

1. Paste your key in the x-api-key header

Every request to JSON2Video carries your API key in a header named x-api-key. Get the key from the API Keys page of the dashboard.

Workflows send it in one of two ways. Use whichever your workflow already has.

Option A: in the node's headers. In the HTTP Request node, turn on Send Headers. Under Header Parameters, set:

Field Value
Name x-api-key
Value YOUR_API_KEY

Do this in every node that calls JSON2Video, including the one that checks the status. A key changed in the first node but not in the second is the most common reason a workflow creates the video and then fails.

Option B: in a Header Auth credential. Set up once and reused by every node:

  1. In the HTTP Request node, set Authentication to Generic Credential Type and Generic Auth Type to Header Auth.
  2. Under Header Auth, select Create new credential.
  3. Set Name to x-api-key and Value to your API key. Save.
  4. Select the same credential in the node that checks the status.

If you imported a tutorial's workflow, the credential is already there: open it and replace its Value with your key.

No Bearer, just the key. The name must be exactly x-api-key, with no spaces around it.

For a workflow you share or run in production, create a dedicated key with the Render role, so you can revoke it without touching anything else. See API keys.

2. Create the video

Set up the first HTTP Request node:

Field Value
Method POST
URL https://api.json2video.com/v2/movies
Send Headers / Authentication your key, as in step 1
Send Body on
Body Content Type JSON
Specify Body Using JSON
JSON the body, below

The body is either a template with variables or a full movie JSON.

A template with variables. This one renders a public example template, a vertical narrated short with three images, with your own first voice-over line:

{
  "template": "2QzqAMLjKkS7dpgUupmI",
  "variables": {
    "text_1": "Hello from n8n. This is my first video."
  }
}

Variables you do not send keep the template's sample values. This template also takes text_2, text_3, image_1 to image_3 (public image URLs) and voice (an Azure voice name). To use your own template, copy its ID from the Templates page of the dashboard.

A full movie JSON. The whole video is described in the body. This one makes a vertical video from an image, a title and a narration that come from earlier nodes (see step 3 for the {{ }} parts):

{
  "resolution": "instagram-story",
  "scenes": [
    {
      "elements": [
        { "type": "image", "src": "{{ $json.image_url }}", "resize": "cover" },
        { "type": "text", "text": {{ JSON.stringify($json.title) }}, "style": "002" },
        { "type": "voice", "text": {{ JSON.stringify($json.script) }} }
      ]
    }
  ]
}

Click Execute step. The answer carries the project ID of the new video:

{
  "success": true,
  "project": "WAEE8PohgVwv2teP",
  "timestamp": "2025-05-28T14:57:34.393Z"
}

The video is not ready yet: it renders in the background. Step 4 gets it when it finishes.

Every field the body accepts is in the Create movie reference and the JSON syntax reference.

3. Put n8n values in the JSON body

Switch the JSON field to Expression. n8n fills in {{ }} only when the field is in Expression mode: the Fixed / Expression switch is above the field, and in Expression mode n8n shows a preview of the result under it. In Fixed mode the {{ $json.title }} text is sent as it is, and the render fails with Expressions unsolved. A body pasted from a tutorial or from this page is the usual cause.

Strings go in quotes, numbers and true/false do not:

{
  "template": "YOUR_TEMPLATE_ID",
  "variables": {
    "title": "{{ $json.title }}",
    "price": {{ $json.price }},
    "show_logo": {{ $json.show_logo }}
  }
}

Text written by an AI node, or typed by a person: use JSON.stringify. If the text has a quote (") or a line break, "{{ $json.text }}" breaks the JSON and n8n refuses to send it ("JSON parameter needs to be valid JSON"). JSON.stringify escapes the text and adds the quotes, so write it without quotes around it:

{
  "text": {{ JSON.stringify($json.text) }}
}

Arrays and objects work the same way, also without quotes. For example, a list of questions an AI node returned, sent to a template variable:

{
  "template": "YOUR_TEMPLATE_ID",
  "variables": {
    "topic": {{ JSON.stringify($json.topic) }},
    "questions": {{ JSON.stringify($json.questions) }}
  }
}

Values from an earlier node use its name: {{ $('Google Sheets').item.json.Title }}. If you rename a node, update the expressions that use its name, or they send an empty value.

4. Wait for the video

A render takes from a few seconds to a few minutes. The usual loop is three nodes after the one that creates the video:

  1. Wait node: 30 seconds.
  2. HTTP Request node, Check status:
    • Method GET, URL https://api.json2video.com/v2/movies.
    • Turn on Send Query Parameters and add Name project, Value {{ $('Create the video').item.json.project }}. Use the name of your own POST node.
    • The same key as the first node: the x-api-key header, or the same credential.
  3. Switch node on {{ $json.movie.status }}:
    • done: the video is ready. Continue the workflow.
    • error: the render failed. The reason is in {{ $json.movie.message }}.
    • Anything else (pending, running): send it to a second Wait node (15 seconds) and back to Check status. In the Switch node, turn on Fallback Output for this branch.

Refer to the POST node by name, as above, rather than with {{ $json.project }}: on the second round of the loop, $json is the answer of Check status, where the ID is in movie.project.

When the status is done:

  • {{ $json.movie.url }} is the MP4. It is public: download it with a plain HTTP Request node, no key needed, or pass the URL to YouTube, Slack, a sheet…
  • {{ $json.movie.duration }}, {{ $json.movie.size }}, {{ $json.movie.width }} and {{ $json.movie.height }} describe the file.

The file is deleted 7 days after the render. Copy it to your own storage if you need it longer: see File retention.

Two more things to set up in a workflow that runs on its own:

  • Cap the loop. Add an IF node before the second Wait that stops when {{ $runIndex }} goes over, say, 40, so a stuck render can't loop forever. A movie still running after 15 minutes counts as timeout: treat it like error.
  • A wrong project ID stops the loop. Check status answers 400 with Movie <project> not found. Check that the project ID was returned by POST /v2/movies with an API key of this same account. The expression points at the wrong node, or the two nodes use keys of different accounts. Retrying gives the same answer.

To avoid polling altogether, add a webhook destination to the body and catch it with a Webhook trigger in a second workflow. See Webhooks.

All the fields and statuses are in the Get movie status reference.

5. Following a tutorial?

Before you run someone else's workflow:

  • Paste your key in every node that calls JSON2Video, or in the credential they share. The tutorial's key, or its placeholder, does not work for you.
  • The free plan makes videos of up to 1 minute. Many tutorials make longer ones; on the free plan they fail with … is longer than your plan allowance (60s). Try with less text, or see the plans.
  • Replace the author's IDs with yours. An ElevenLabs connection ID, a voice ID or a template ID in the body belong to the author's account. Use your own connection, or remove the connection to use JSON2Video's own voices (they cost credits). Public templates work for anyone; a private template of the author's does not.

6. Common errors

When POST /v2/movies refuses a request, n8n shows the error on the node that created the video. When a render fails later, the reason comes back in movie.message from Check status, with status: "error".

Message Where Fix
Invalid API Key The node, any call The key is missing a piece, has extra text such as Bearer, or the header is not named x-api-key. Paste the key alone, in every node that calls JSON2Video.
API key not associated with any account The node, any call The key looks right but is not a key of any account: it was deleted, or it comes from the tutorial. Paste your own key.
API Key not available / API Key not provided The node, any call No key was sent. Turn on Send Headers or select the credential in that node.
JSON parameter needs to be valid JSON n8n, before sending Text from an earlier node has a quote or a line break. Use {{ JSON.stringify($json.text) }} without quotes around it. See step 3.
Source URL is required: the image element in Scene #2, Element #1 has no "src"… (code media_src_required) POST, the node An image, video or audio URL arrived empty. Open the node's input and check that the mapped field shows an https:// link. Usually an earlier node returned no URL, or the field path is wrong.
Source URL is required for image element in Scene #1, Element #2 movie.message Same as above, for a template variable: the variable that fills the src arrived empty.
Expressions unsolved: … movie.message The {{ }} arrived as text. Switch the JSON field to Expression. See step 3.
Connection my-elevenlabs not found in your list of connections. Add your connection from the dashboard. movie.message The connection ID is the tutorial author's. Add your own in Connections and use its ID, or remove connection.
Prompt is empty for image element. Empty string is not allowed in Scene #1, Element #2 movie.message An AI image prompt arrived empty: the node that writes the prompts returned nothing for it, or the expression points at the wrong field.
Movie duration (95s) is longer than your plan allowance (60s). Upgrade your plan movie.message The free plan makes videos of up to 1 minute. Shorten the text or the scenes, or see the plans.

More messages and their fixes are in Errors.

See also