Skip to content

n8n

This page builds one working automation end to end: an inbound WhatsApp message creates a task named Write back to <contact>, linked to that contact.

It uses n8n-nodes-alphone, the community node for AlphOne. For the engine neutral view, and for driving AlphOne from any other engine with plain HTTP, see the automation guide.

  • An n8n instance you administer, self hosted or cloud
  • AlphOne 0.7.0 or newer, reachable from n8n over HTTP
  • An AlphOne login, to mint a token

In n8n, open Settings then Community nodes then Install, and enter n8n-nodes-alphone. Only Owner and Admin accounts may install community nodes.

Two nodes appear afterwards. AlphOne performs actions, and AlphOne Trigger starts a workflow when something happens.

Self hosted instances need community packages enabled, which is the default. If installation is refused, set N8N_COMMUNITY_PACKAGES_ENABLED=true and, until the node passes n8n verification, N8N_UNVERIFIED_PACKAGES_ENABLED=true.

An engine cannot hold a browser session, so it authenticates with a token. On the AlphOne host:

Terminal window
alphone token create -email you@example.com -name "n8n" \
-scope meta:read -scope webhooks:write -scope tasks:write -scope contacts:read

Those four cover this guide: meta:read for the credential test, webhooks:write for the trigger to register and remove its subscription, tasks:write to create tasks, and contacts:read to look contacts up. Drop any your workflow does not need.

The secret prints once and is stored only as a hash. Copy it now, because it cannot be recovered, only replaced.

A token acts as the user who created it, so create it against the account whose work the automation should own. Disabling that user stops their tokens the way it already stops their sessions.

Two limits narrow it further. Each -scope names an area and whether the token may write there, and a token holds nothing it was not granted. Leave -scope out and the token gets every area, which is rarely what an automation needs. Area names are exact, so a typo like contact:read is refused when you mint it rather than failing later.

A token also never reaches further than the person who created it. Mint it against an account that already does the work you are automating.

A token also expires. Without -ttl it lasts ninety days, and after that every request answers invalid token. Pass -ttl 30 for a shorter life, or -ttl never for one that does not expire. Run alphone token list to see the scopes and the expiry date of every token you hold.

Open the Credentials tab and press Create credential.

The Personal page with the Credentials tab selected and the Create credential button highlighted.

Search for AlphOne API and select it.

The Add new credential dialog with AlphOne API typed in the search field and highlighted in the results.

Fill in two fields and save.

FieldValue
Base URLwhere n8n reaches AlphOne, with no trailing slash
API Tokenthe secret from step 2

The AlphOne account credential form showing the Base URL set to host.docker.internal and the API token masked.

The base URL depends on where each side runs:

AlphOne runsBase URL from inside n8n
On your machine, n8n in Dockerhttp://host.docker.internal:8080
Both in the same compose projecthttp://alphone:8080
A deployed instanceits public URL

localhost inside a container means the container itself, never your machine, so it will not reach AlphOne.

Press the test button. It asks AlphOne for its version, which needs a valid credential, so a success there proves the whole connection.

Open the Workflows tab and press Create workflow.

The Personal page with the Workflows tab selected and the Create workflow button highlighted.

Press Add first step and search for alphone.

The empty workflow canvas with the Add first step panel open and alphone typed in the search field.

The node offers a trigger for each event it supports.

The AlphOne node panel listing one trigger per event, among them on whats app message received.

Choose On whats app message received.

Pick the credential from step 3, and confirm the event reads WhatsApp Message Received.

The AlphOne Trigger node with its credential selected, the WhatsApp Message Received event chosen, and the Execute step button highlighted.

Press Execute step. n8n waits for a real event.

The trigger waiting, showing Listening for test event and an instruction to create an event in AlphOne.

While it listens, send a WhatsApp message to your connected number. The envelope arrives:

The trigger output showing one item with id, event, occurred at, and a data object holding contact id, contact name, conversation id, external id, and text.

Every delivery carries the same four fields. id names the event and stays the same across retries, so store it if you need to drop duplicates. data carries the subject, and for whatsapp.message.received that means conversation_id, contact_id, contact_name, external_id, and text. The webhooks reference documents the envelope in full.

Testing this way needs no published workflow, which makes it the fastest way to see real data before building the rest.

Press the + after the trigger. The node groups its actions by resource, one group per kind of record it reads and writes.

The workflow canvas with the trigger connected, and the node details panel listing the actions grouped by resource.

Choose Create a task and set:

FieldValue
ResourceTask
OperationCreate
TitleWrite back to {{ $json.data.contact_name }}
Due Onleave the default

Then Add Field under Additional Fields:

FieldValue
Contact ID{{ $json.data.contact_id }}

Switch each of those to expression mode with its fx toggle, then type the value without a leading =. n8n adds that prefix itself when it stores the parameter, so typing one leaves a stray = in the value. A stray = in Title is stored as part of the task title, and a stray = in Contact ID is refused with a VALIDATION error naming the bad uuid, which the node reports as a failed step. The small preview under each field shows the resolved value, so check it reads Write back to Maria Perez and a bare uuid before running.

Press Execute step.

The Create a task node with its title and contact id expressions resolved, and the output showing the created task with a Node executed successfully message.

The task exists in AlphOne now, linked to the contact who wrote in.

Name the workflow and press Publish.

The finished workflow with the trigger and the task node connected, and the Publish button highlighted.

Publishing is what registers the webhook. The trigger asks AlphOne to create a subscription and stores its id and its signing secret in workflow static data. An unpublished trigger has no subscription, so nothing is delivered to it.

Confirm AlphOne agrees, using the token from step 2:

Terminal window
curl -s https://your-domain/api/graphql \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"query":"{ webhooks { id url events } }"}'

A subscription pointing at your n8n webhook url means the loop is live. From now on, every inbound WhatsApp message creates its task on its own.

A task created with an API token records token:<name> in its origin_source, so work an automation created stays distinguishable from work a person typed. Attribution comes from the credential rather than the request, so a workflow cannot claim to be someone else, and it needs nothing from you.

AlphOne signs every delivery with HMAC-SHA256 over the exact bytes sent, and the node verifies that signature before running the workflow, so a forged request is rejected. Delivery is at least once, retried with a widening wait for 24 hours, so a workflow that survives a restart catches up on its own. Answer quickly, because AlphOne waits 10 seconds.

To see what happened from the AlphOne side, read the delivery queue:

Terminal window
docker compose exec postgres psql -U postgres -d alphone -c \
"SELECT event_name, status, attempts, last_error
FROM core.webhook_deliveries ORDER BY created_at DESC LIMIT 5"

delivered with attempts = 1 means the chain worked first time.

SymptomCause
The credential test failsThe base URL has a trailing slash, or says localhost where the container cannot reach AlphOne, or the token expired
invalid tokenThe token expired, was revoked, or the token id was pasted instead of the secret. Run alphone token list to see its expiry. Only the value starting a1_ authenticates
scope required: contacts:writeThe token was not granted that area. Mint a replacement with the -scope it needs, tokens cannot be widened in place
Nothing arrives after publishingNo subscription exists. Ask for webhooks and republish
A task titled with literal {{ }}The field is not in expression mode. Use its fx toggle
The task node fails with a validation error naming the id, previews show a leading =An = was typed into the expression editor. n8n adds it, so delete yours
Deliveries stuck pending with subscriber answered 404A subscription outlived its workflow. Delete it with the deleteWebhook mutation

The same two nodes cover every event AlphOne publishes, listed in the webhooks reference, and every action the node offers. A schedule trigger with Get many tasks filtered by due_before makes a morning digest of overdue work, with no trigger registration involved.

The package ships example workflows in its examples folder. Import one from the n8n canvas menu, then open each AlphOne node and pick your credential, which the files leave as a placeholder.

  • overdue-task-digest.json collects the tasks you have not finished and builds a message from them, every morning at eight.
  • whatsapp-message-to-task.json creates a task the moment a WhatsApp message arrives, linked to the contact AlphOne resolved it to.
  • import-to-daily-tasks.json turns a finished contact import into a call list spread over days, twenty a day, with each task carrying its import row so a re-run creates nothing twice. The automation guide explains the recipe behind it.