---
title: "n8n Integration - Generate Images in Any Workflow"
description: "Render on-brand images inside any n8n workflow with one HTTP Request node. Map trigger data to a template's fields and get the finished image back on the node."
url: "https://www.imejis.io/integrations/n8n"
image: "https://www.imejis.io/images/integrations/rest-api.svg"
---

# n8n Integration - Generate Images in Any Workflow

n8n renders Imejis designs as part of any automation you build, self-hosted or
on n8n Cloud. Design a template once, mark the layers that change as dynamic
fields, then drop in a single **HTTP Request** node. The finished image comes
back on that node's own output, so there is no webhook to wait on and no second
workflow to catch a callback.

Unlike Airtable or Google Sheets, n8n talks to the render API **directly**. No
middleman platform sits in between.

## What you can automate

- **Social graphics from new records**: a row, issue or CRM contact becomes an
  on-brand image the next node posts.
- **Personalised emails**: one visual per recipient, generated in the loop.
- **Certificates, receipts and badges**: a form submission or payment becomes a
  branded single-page PDF.

## How to set it up

1. Add an **HTTP Request** node. Method **POST**, URL set to your design's
   render endpoint:

   ```text
   https://render.imejis.io/v1/<designId>
   ```

2. Add the `dma-api-key` header with your API key, and set Body Content Type to
   **JSON**.

3. Send the fields you want to change, using n8n expressions to map data from
   earlier nodes:

   ```json
   {
     "title.text": "{{ $json.title }}",
     "subtitle.text": "{{ $json.subtitle }}"
   }
   ```

   Omitted fields fall back to the design's defaults.

## Set Response Format to match what you asked for

This is the step that trips people up, because n8n decides how to read the
response before it sees it.

| You want | Append to the URL | n8n Response Format | Use downstream |
| --- | --- | --- | --- |
| The image file | nothing | **File** | the binary on the node output |
| A stored URL | `?delivery=hosted` | **JSON** | `{{ $json.url }}` |
| A private, expiring URL | `?delivery=signed` | **JSON** | `{{ $json.url }}` |

Leave Response Format on **File** while asking for `?delivery=hosted` and n8n
writes the JSON body into a binary field, which then fails further down the
workflow with an error that points at the wrong node.

With `?delivery=hosted` the node receives:

```json
{
  "success": true,
  "delivery": "hosted",
  "url": "https://...",
  "format": "png",
  "file": { "bucket": "imejis", "path": "hosted-exports/...", "size": 46819 }
}
```

## Picking a delivery mode in a loop

In a batch, the delivery mode decides what you are storing.

- **File** keeps the bytes inside the execution. Fine for one image you email
  immediately, heavy if you are looping over hundreds.
- **hosted** stores the render once and hands back a permanent public URL, which
  is what you want when the URL is written back into a database or a CMS.
- **signed** does the same but expires, default 60 minutes, up to 7 days.

Every render counts as one render whichever mode you choose.

## Going further

- Exact node settings, including the expression syntax, are on the
  [n8n API page](/apis/n8n).
- Ten worked workflows are in
  [n8n image automation](/blogs/integrations/n8n-image-automation).
- Prefer a managed platform? The same design works from
  [Zapier](/integrations/zapier) or [Make](/integrations/make).
- Output formats are PNG, JPEG, WebP and single-page PDF, chosen with
  `?format=`. See the [pricing page](/pricing) for render allowances.
