# Automate image resizing with n8n
> Connect n8n to the SocialCutter API: new-image trigger, HTTP Request node, routing outputs to social networks and CMS, an importable workflow and cost per run.
- URL: https://socialcutter.theboomer.dev/en/guides/n8n/
- Idioma: en
- Familia: ia
- Actualizado: 2026-09-24
- Palabras clave: n8n, automation, HTTP Request, Webhook, SocialCutter, social media, API key
## Why automate

One master image serves Instagram, LinkedIn, X and the blog header. Doing it by hand, format by format, does not scale when you publish daily or when a catalogue holds hundreds of products. n8n fits because it already watches where new images appear and because it can call any HTTP API. SocialCutter crops centrally to the exact dimensions of each destination and returns one URL per output; n8n moves that URL to the right place.

## How SocialCutter fits into n8n

The flow has three steps:

1. A trigger detects a new image.
2. An **HTTP Request** node calls SocialCutter with that image URL and the list of destinations.
3. The response carries one output per destination; it is routed to social networks or the CMS.

SocialCutter exposes a REST API at `https://api.socialcutter.theboomer.dev` and authentication goes in the `X-API-Key` header (or `Authorization: Bearer`). The full reference is at https://docs.socialcutter.theboomer.dev.

## The trigger: when a new image arrives

It depends on where the image shows up:

- **Webhook**: a `Webhook` node receives a `POST` with the image URL. Most flexible if you already have a form, your own panel or a script that uploads images.
- **Google Drive**: the `Google Drive Trigger` node fires on `File Created` or `File Updated` in a watched folder.
- **SharePoint**: the `Microsoft SharePoint` node with the file-created event covers the same case in Microsoft 365 environments.

In every case the trigger must hand over at least a public image URL. The SocialCutter API needs to download it: if the source requires a session, serve the image through a signed link or upload the file with the multipart endpoint.

## Calling SocialCutter from the HTTP Request node

### Store the API key in a credential

Create a **Header Auth** credential:

- Name: `X-API-Key`
- Value: `sc_your_key`

Select it in the HTTP Request node. That keeps the key out of the workflow JSON so it is not leaked when you export it. As an alternative on self-hosted servers, set the `SOCIALCUTTER_API_KEY` environment variable and reference `{{ $env.SOCIALCUTTER_API_KEY }}`.

### The request body

- Method: `POST`
- URL: `https://api.socialcutter.theboomer.dev/api/v1/images/process`
- Body: JSON

```json
{
  "source": { "type": "url", "value": "={{ $json.image_url }}" },
  "destinations": [
    { "platform": "instagram", "format": "post" },
    { "platform": "linkedin", "format": "post" },
    { "platform": "twitter", "format": "post" }
  ],
  "options": { "fit_mode": "cover" }
}
```

`source` accepts `url` or base64; `destinations` is the list of platform and format. `fit_mode: cover` scales and crops the excess centrally, which is the default behaviour. If you need to fit the whole image, use `contain` with `background_color`.

### Sending the image: URL in JSON, multipart or binary

The HTTP Request node can hand the image over in three different ways, and picking the wrong one is the usual reason "the node will not upload the image". Under **Send Body → Body Content Type**, n8n documents these options: **Form URLencoded**, **Form-Data**, **JSON**, **n8n Binary File** and **Raw**.

**1. The URL inside the JSON, which is the normal path with SocialCutter.** The image never leaves n8n: it travels as text in the `source` field and the API downloads it itself. The node needs no binary property at all.

- Body Content Type: `JSON`
- Body: `{ "source": { "type": "url", "value": "https://your-cdn.com/master.jpg" }, "destinations": [...] }`

`source` takes a public URL or a base64 string already present in the JSON. If the source requires a session, or if the image bytes are already inside n8n, you have to upload the file through route 2.

**2. multipart/form-data with the file as a field.** Here the node does send the bytes. n8n documents this combination as the fix for the **415 Unsupported media type** error:

- Body Content Type: `Form-Data` (the node sends `multipart/form-data`)
- Add a **Body Parameter** and set its **Type** to `n8n Binary File`
- **Name**: the field name the API expects, that is the `file` field of the upload endpoint
- **Input Data Field Name**: the name of the item's binary property, usually `data`

**3. n8n Binary File as the whole body.** It sends the file contents as the request body, with the file's own content type. Only valid if the API accepts a raw body; if it expects a named field inside a form, it will not work.

### Why the node "will not upload the image"

The usual failures, in order of frequency:

- **Body Content Type set to JSON with a binary item**: the binary is ignored, the server receives JSON with no file and answers with a validation error. If the API expects a URL, this is the correct route and there is nothing to upload.
- **Form-Data with a parameter of type Form Data**: it sends a text field holding the file name, not the bytes.
- **The item carries no binary**: if the previous node only produced JSON (a URL, an object), there is no file to send. Download it first: an HTTP Request node with `GET` and **Response Format: File** puts the download into a binary property (name it in **Put Output in Field**, for example `data`) and the multipart node can then send it.
- **Mismatched Input Data Field Name**: the name must match the item's binary property exactly (`data`, `image`, whatever it is).
- **Wrong file name**: n8n documents the case of a file arriving under a different name and solves it by setting the name on the binary property from a Code node.

## Routing the outputs: social networks and CMS

The response includes `image_id` and an `outputs` array, one entry per destination, with the result URL, the platform, the format and the dimensions. Add a **Split Out** node on the `outputs` field to turn it into one item per output, then route by platform:

- Instagram, LinkedIn, X and TikTok have dedicated n8n nodes: pass each output URL to the matching publish node.
- For a CMS without an official node, chain another HTTP Request node pointing at the media upload URL (for example the CMS media API) using the output URL as the file to download.

Keep a shared field, such as `platform`, so the router (`Switch`) knows where to continue.

## Minimal importable workflow

Paste this JSON into n8n with **Import from clipboard**. It brings the trigger and the API call; add the routing afterwards.

```json
{
  "name": "SocialCutter - image fan-out",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "socialcutter-new-image",
        "responseMode": "onReceived"
      },
      "id": "webhook-1",
      "name": "Webhook new image",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [220, 300],
      "webhookId": "socialcutter-new-image"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.socialcutter.theboomer.dev/api/v1/images/process",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            { "name": "X-API-Key", "value": "={{ $env.SOCIALCUTTER_API_KEY }}" }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ source: { type: 'url', value: $json.image_url }, destinations: [{ platform: 'instagram', format: 'post' }, { platform: 'linkedin', format: 'post' }], options: { fit_mode: 'cover' } }) }}",
        "options": {}
      },
      "id": "http-1",
      "name": "SocialCutter process",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 300]
    }
  ],
  "connections": {
    "Webhook new image": {
      "main": [[{ "node": "SocialCutter process", "type": "main", "index": 0 }]]
    }
  },
  "settings": { "executionOrder": "v1" }
}
```

If you prefer the Header Auth credential, delete the `headerParameters` block and select the credential in the node. The `webhookId` must match the `path` for the webhook URL to work.

## Error handling and retries

- Turn on **Retry On Fail** on the HTTP Request node with 2 or 3 attempts: it covers transient network failures.
- Enable **Continue On Fail** if you want a failed output not to abort the whole workflow.
- Send the `Idempotency-Key` header with a stable value (for example the file id) so a retry does not create duplicate work.
- Most common error codes: `401` (missing or revoked key), `413` (file over 5 MB), `422` (validation) and `429` (quota exhausted).

## Cost per run

- 1 use per destination (platform and format) per request.
- Repeated destinations in the same request are not charged twice.
- Failed processing is refunded.

A run that asks for Instagram post, LinkedIn post and X post spends 3 uses. If the trigger receives bursts of images, batch before calling or use the `POST /api/v1/images/batch` endpoint.

## Alternatives to n8n

If you already use another automation platform, the pattern is the same: a trigger and an HTTP call with the `X-API-Key` header. See the official docs for the generic HTTP node in [Make](https://www.make.com/en/help/apps/built-in-apps/http) and [Zapier](https://help.zapier.com/hc/en-us/articles/8496293271053).

## Next steps

- API guide with curl: [Process images with the API from the terminal](/en/guides/curl/)
- Python guide: [Automate SocialCutter with Python](/en/guides/python/)
- MCP guide: [Use SocialCutter from your LLM or editor](/en/guides/mcp/)
- API reference: https://docs.socialcutter.theboomer.dev