# Automate with n8n

URL: https://briq.cloud/docs/guides/automate-with-n8n

> Run n8n with a public URL for webhooks, then have the agent build, activate and test workflows through its API.

Recipe:

- [n8n](https://briq.cloud/cookbook/n8n.md): Workflow automation: webhooks, schedules and integrations (WhatsApp, Slack, Gmail…). The agent builds workflows with briq_exec ["node", "/briq/n8n-api.mjs", "POST", "/workflows", "-"]. Run it with expose: "public" so webhooks reach it.

The [n8n recipe](https://briq.cloud/cookbook/n8n) runs n8n on one briq: workflows that start on a webhook, a
schedule or a message, then call the services n8n knows. The agent builds them through n8n's API;
you check them in the editor.

```text
briq_run({ recipe: "n8n", expose: "public" })
→ bq_… n8n (n8nio/n8n:latest) running · url: https://n8n-k3x9.briq.run/ · cost so far … · sleeps at 18:42 UTC unless used
  outputs:
    N8N_OWNER_EMAIL=owner@n8n.local
    N8N_OWNER_PASSWORD=…
    URL=https://n8n-k3x9.briq.run/
```

What happens:

1. briq makes n8n's owner before n8n starts. The editor asks for a sign-in from the first visit.
2. n8n knows its URL: its webhooks are under `https://n8n-k3x9.briq.run/webhook/`.
3. Workflows, credentials and runs are kept in SQLite on the briq's volume.

## Build a workflow

A workflow is JSON: its nodes and how they connect. This one answers a webhook:

```json
{
  "name": "Echo",
  "nodes": [
    { "name": "Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [0, 0],
      "parameters": { "httpMethod": "POST", "path": "echo", "responseMode": "responseNode" } },
    { "name": "Reply", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [300, 0],
      "parameters": { "respondWith": "json", "responseBody": "={{ { \"got\": $json.body.text } }}" } }
  ],
  "connections": { "Webhook": { "main": [[{ "node": "Reply", "type": "main", "index": 0 }]] } },
  "settings": {}
}
```

Create it, then activate it:

```text
briq_exec({ briq: "bq_…", cmd: ["node", "/briq/n8n-api.mjs", "POST", "/workflows", "-"], stdin: "<the workflow>" })
→ {"id":"O3YAE75kPu683zmH","name":"Echo","active":false,…}

briq_exec({ briq: "bq_…", cmd: ["node", "/briq/n8n-api.mjs", "POST", "/workflows/O3YAE75kPu683zmH/activate"] })
→ {"id":"O3YAE75kPu683zmH","name":"Echo","active":true,…}
```

Call it from anywhere:

```bash
curl -s https://n8n-k3x9.briq.run/webhook/echo -H 'content-type: application/json' -d '{"text":"hello"}'
```

```text
{"got":"hello"}
```

* `n8n-api.mjs` takes any path of [n8n's public API](https://docs.n8n.io/api/) after `/api/v1`:
  `GET /workflows`, `GET /executions?workflowId=…`, `PUT /workflows/{id}`.
* Its first call signs in as the owner and makes an API key, kept on the volume for the next calls.
* `-` reads the body from `stdin`, so the agent never escapes JSON on a command line.

## Sign in to the editor

Open the URL and sign in with `N8N_OWNER_EMAIL` and `N8N_OWNER_PASSWORD`. Add credentials there
(Credentials → Add): a WhatsApp account, a Gmail sign-in, an API key. n8n keeps them encrypted on
the volume, and a workflow names them by id. The agent then uses them without holding them.

## WhatsApp and Messenger

n8n's **WhatsApp Trigger** node starts a workflow on each message, and its **WhatsApp Business
Cloud** node replies. Meta sends messages to a public HTTPS URL: the briq's. Add the Meta app's
credentials in the editor, then activate the workflow. For Messenger, or to write the bot as your
own code, see [Run a webhook bot](https://briq.cloud/docs/guides/run-a-webhook-bot).

## With a database

Put a Postgres in the same stack, for the data your workflows keep:

```text
briq_run({ recipe: "postgres", stack: "shop" })
briq_run({ recipe: "n8n", stack: "shop", expose: "public" })
```

In n8n's Postgres credential, use `PGHOST`, `PGUSER`, `PGPASSWORD` and `PGDATABASE` from the
postgres outputs, with SSL off: the stack's private network has no TLS.

## Schedules

A Schedule Trigger runs only while the briq is awake. A webhook wakes it; a timer cannot. A
workflow on a schedule needs `sleep: "never"` (Pro plan), or a window longer than the time between
two runs. See [Lifecycle and sleep](https://briq.cloud/docs/concepts/lifecycle-and-sleep).

## When it does not work

* **`The requested webhook "POST echo" is not registered`**: the workflow is not active, or was
  activated less than a second ago. `/webhook-test/` paths answer only while the editor listens.
* **Webhook URLs start with `https://localhost/`**: the briq was created without `expose`. n8n reads
  its URL at boot: destroy the briq and run it again with `expose: "public"`.
* **`401` from a sender**: the URL is private. A webhook sender cannot pass its token: use
  `expose: "public"`.
* **The first request after a while is slower**: the briq was asleep and woke for it.

## Good to know

* **`small` at least**: n8n uses about 700 MB once started.
* **The owner's password comes from briq** at every start, so it cannot be changed in the editor.
* **The Code node runs JavaScript.** Python is not in the image.
* **n8n deletes runs older than 14 days** by default (`EXECUTIONS_DATA_MAX_AGE`, in hours).
* **Each run is a webhook visit**, so a busy workflow keeps the briq awake, and billed.
