n8n automation for Sparks (developers)
This guide is for developers and integrators connecting n8n (self-hosted or cloud) to Sparks. It covers auth, REST surfaces, webhooks, example workflows, custom nodes, and operations.
Short overview in the app repo: Vistameet-Teams/docs/N8N.md · OpenAPI: Vistameet-Teams/docs/openapi/sparks-automation-v1.yaml.
1. Overview
Sparks offers several integration paths. The most important ones for n8n:
| Direction | Mechanism | Typical use cases |
|---|---|---|
| n8n → Sparks chat | Incoming webhook → Matrix room | Alerts from GitHub, Jira, monitoring, CRM |
| n8n → calendar / tasks / chat | REST /api/v1/automation with API key spk_… | Create events/tasks, send messages |
| Sparks → n8n | Outgoing event webhooks (Account UI) | Meeting created/ended, webinar registration |
| Sparks → n8n (call lifecycle) | Env CONF_CALL_LOG_WEBHOOK_URL | Join / room end → CRM, digest |
| Optional | Custom nodes n8n-nodes-sparks | Calendar, tasks, chat without hand-built HTTP nodes |
┌─────────────┐ spk_ key / webhook ┌──────────────────┐
│ n8n │ ──────────────────────────► │ Sparks Node API │
│ workflows │ ◄────────────────────────── │ + Matrix bot │
└─────────────┘ event / call-log POST └──────────────────┘
Not intended for n8n: LiveKit media control, Matrix E2EE crypto bootstrap, Sygnal push registration.
2. Prerequisites
2.1 Sparks side
- Reachable API base URL (e.g.
https://api.example.comor local Node server) - Account that can create API keys: Account → AI access / MCP
- For chat write via automation REST: scope
matrixand server-sideMATRIX_JWT_SECRET(same as MCP) - For incoming webhooks (bot → room):
MATRIX_WEBHOOK_ACCESS_TOKEN(orMATRIX_BOT_ACCESS_TOKEN),MATRIX_HOMESERVER_URL,WEBHOOK_MAPPINGS - Database migrations current (table
automation_webhook_subscriptionsfor outgoing events)
2.2 n8n side
- n8n with HTTP Request and Webhook nodes (built-in)
- Optional: custom extension path for
n8n-nodes-sparks(self-hosted) - Network: n8n must reach Sparks; Sparks must reach n8n webhook URLs (for triggers)
3. Authentication and scopes
3.1 API key spk_… (recommended for REST)
- Open Account → AI access / MCP (
/mcp) - Create a key and choose scopes (opt-in)
- Store the plaintext once
Headers (either is enough):
Authorization: Bearer spk_…
or
X-Sparks-Api-Key: spk_…
Valid for:
| Endpoint | Purpose |
|---|---|
/api/mcp | MCP Streamable HTTP (AI clients) |
/api/v1/automation/* | REST for n8n |
/v1.0/me/calendar/events, /v1.0/me/tasks, /v1.0/me/chats/… | Graph-style aliases |
Scopes (selection):
| Scope | REST relevance |
|---|---|
calendar | Read/create events |
tasks | Read/create tasks |
matrix | List rooms, send messages (plaintext-capable) |
calls | mainly MCP: call log, call details, meeting transcripts (list_calls, get_call, get_call_transcript) |
memory / contacts / files / activity | mainly MCP tools |
Rotate and revoke keys on the same Account page. Do not give LiveKit/transcriber service tokens to n8n.
3.2 Incoming webhook ID
Path parameter webhookId is the secret. Room mapping via env WEBHOOK_MAPPINGS (no user API key).
3.3 Keycloak Bearer
Account/appointment REST (/api/account, /api/local-appointments, …) requires OIDC. Awkward in n8n (token refresh). Prefer spk_… + automation API.
4. Quick wins
4.1 n8n → Matrix chat (incoming webhook)
Endpoints (equivalent):
POST /webhooks/incoming/:webhookId(canonical)POST /api/webhooks/incoming/:webhookId(alias)
Body:
{
"text": "Deployment succeeded"
}
Alternatives: message, body, or content.
Server env (example):
MATRIX_WEBHOOK_ACCESS_TOKEN=syt_…
MATRIX_HOMESERVER_URL=https://matrix.example.com
WEBHOOK_MAPPINGS={"n8n":"!roomId:matrix.example.com","github":"!other:matrix.example.com"}
# optional: WEBHOOK_ROOM_ID=!room:… → webhookId "default"
n8n: HTTP Request → POST → https://<api>/webhooks/incoming/n8n → JSON body.
The bot must be a member of the target room. Details: app repo docs/INCOMING_WEBHOOKS.md.
4.2 Call lifecycle → n8n
On the Sparks Node server:
CONF_CALL_LOG_WEBHOOK_URL=https://<n8n-host>/webhook/sparks-call
CONF_CALL_LOG_WEBHOOK_SECRET=optional-bearer
# CONF_CALL_LOG_NOTIFY_PARTICIPATION_START=false
Payloads include kind=participation_start and kind=livekit_room_session_ended. Contract: app repo docs/CONF_TEAM_CALLLOG_S2S_DELIVERABLES.md.
In n8n: Webhook trigger with matching path; optionally verify Authorization: Bearer ….
5. Automation REST API
Base: {API_BASE}/api/v1/automation
Auth: spk_… + scope
OpenAPI: app repo docs/openapi/sparks-automation-v1.yaml
5.1 Endpoints
| Method | Path | Scope | Description |
|---|---|---|---|
GET | /calendar/events?start=&end= | calendar | Events in range (ISO-8601) |
POST | /calendar/events | calendar | Create event |
GET | /tasks | tasks | List tasks |
POST | /tasks | tasks | Create task |
GET | /chats/rooms | matrix | Joined Matrix rooms |
POST | /chats/rooms/:roomId/messages | matrix | Send text message |
Graph aliases (same handlers):
GET/POST /v1.0/me/calendar/eventsGET/POST /v1.0/me/tasksGET /v1.0/me/chats/roomsPOST /v1.0/me/chats/rooms/:roomId/messages
5.2 Examples
Create event
curl -sS -X POST "$API_BASE/api/v1/automation/calendar/events" \
-H "Authorization: Bearer $SPK_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "Standup",
"start": "2026-08-01T09:00:00.000Z",
"end": "2026-08-01T09:15:00.000Z",
"timeZone": "Europe/Berlin"
}'
Create task
curl -sS -X POST "$API_BASE/api/v1/automation/tasks" \
-H "Authorization: Bearer $SPK_KEY" \
-H "Content-Type: application/json" \
-d '{ "title": "Follow-up from n8n", "priority": 5 }'
Send Matrix message
curl -sS -X POST "$API_BASE/api/v1/automation/chats/rooms/!abc:example.com/messages" \
-H "Authorization: Bearer $SPK_KEY" \
-H "Content-Type: application/json" \
-d '{ "text": "Hello from n8n" }'
5.3 Typical error codes
| HTTP | Meaning |
|---|---|
401 | Missing / invalid / revoked key |
403 | Missing scope (MCP_SCOPE_MISSING) |
400 | Validation (e.g. missing subject) |
503 | DB/calendar disabled or Matrix session unavailable |
6. Outgoing event webhooks (triggers for n8n)
6.1 Configuration
UI: Account → Automation (/automation)
- HTTPS URL (
http://localhost…allowed locally) - Choose events
- Optional secret → header
X-Sparks-Signature: sha256=<hmac>
REST (Keycloak Bearer, Account API):
| Method | Path |
|---|---|
GET / POST | /api/account/me/automation-webhooks |
PATCH / DELETE | /api/account/me/automation-webhooks/:id |
6.2 Events
| Event | When | Recipient logic |
|---|---|---|
meeting.created | Local appointment created | Organizer (creatorKeycloakSub) |
meeting.ended | LiveKit room finished | Creator when room name = appointment id |
registration.created | Webinar registration | Creator + webinar write permissions |
6.3 Delivery payload
POST <your-n8n-url>
Content-Type: application/json
User-Agent: Sparks-Automation-Webhook/1.0
X-Sparks-Event: meeting.created
X-Sparks-Delivery: evt_…
X-Sparks-Signature: sha256=… # only if secret set
{
"id": "evt_a1b2c3…",
"type": "meeting.created",
"createdAt": "2026-07-30T12:00:00.000Z",
"data": {
"appointmentId": "…",
"subject": "Standup",
"startTime": "…",
"endTime": "…",
"matrixRoom": "!…:example.com",
"meetingType": null
}
}
Server-side timeout ~10 s. Last error / last delivery shown in the Account UI.
6.4 Verify HMAC (n8n / middleware)
Signature = HMAC-SHA256 over the raw request body with the configured secret, hex, prefix sha256=.
7. Example n8n workflows
7.1 Alert → Matrix
- Trigger (GitHub / cron / other webhook)
- Set / Code: build text from payload
- HTTP Request →
POST …/webhooks/incoming/<id>with{ "text": "…" }
7.2 Meeting ended → Notion / CRM
- Account → Automation: event
meeting.ended, URL = n8n webhook - n8n Webhook → IF
type === meeting.ended→ Notion/CRM/HTTP
7.3 Ticket → calendar event
- Trigger from ticketing system
- HTTP Request
POST /api/v1/automation/calendar/eventswithspk_…(scopecalendar) - Optional: room message with join hint (
matrixscope or incoming webhook)
7.4 Webinar registration → Slack/Teams
- Event
registration.createdto n8n webhook - Format message for external channel system
8. Custom nodes (n8n-nodes-sparks)
In the app repo: folder n8n-nodes-sparks/.
| Component | Content |
|---|---|
| Credential Sparks API | Base URL + spk_… |
| Node Sparks | Calendar list/create, task list/create, chat list rooms / send message |
Install (self-hosted, sketch):
cd ../Vistameet-Teams/n8n-nodes-sparks
npm install
npm run build
export N8N_CUSTOM_EXTENSIONS=/absolute/path/to/n8n-nodes-sparks
# restart n8n
Event triggers stay on Account UI + n8n Webhook node (no dedicated trigger node required).
9. Operations and environment variables
| Variable | Purpose |
|---|---|
MATRIX_WEBHOOK_ACCESS_TOKEN / MATRIX_BOT_ACCESS_TOKEN | Bot for incoming webhooks |
MATRIX_HOMESERVER_URL | Homeserver |
WEBHOOK_MAPPINGS | JSON webhookId → roomId |
WEBHOOK_ROOM_ID | Room for webhookId=default |
CONF_CALL_LOG_WEBHOOK_URL | Outbound call lifecycle → n8n |
CONF_CALL_LOG_WEBHOOK_SECRET | Optional Bearer |
MATRIX_JWT_SECRET | Matrix session for automation/MCP chat |
DATABASE_URL | Required for keys and outgoing webhooks |
SPARKS_DB_CALENDAR | 0 disables DB calendar (REST returns 503) |
Outgoing webhooks migration: automation_webhook_subscriptions (Prisma). Locally with drift: npx prisma migrate deploy (not necessarily migrate reset).
10. Security
- Keep scopes minimal; treat keys like passwords
- Incoming
webhookId= secret (no HMAC yet) → long random IDs, do not log URLs - Outgoing: set a secret and verify the signature in n8n
- E2EE: automation/MCP cannot read encrypted Matrix content; writes only via plaintext-capable sessions
- Do not put admin Graph keys (
ADMIN_GRAPH_API_KEY) or LiveKit service tokens in n8n - Tenant gates for MCP/n8n may still be tightened operationally (roadmap)
Related: End-to-end encryption – decision guide, Account – AI access / MCP.
11. Troubleshooting
| Symptom | Check |
|---|---|
401 on automation | Correct key? spk_ prefix? Revoked? |
403 / MCP_SCOPE_MISSING | Add the required scope on the key |
Incoming 404 Webhook not found | WEBHOOK_MAPPINGS / default + WEBHOOK_ROOM_ID |
Incoming 503 | Bot token + homeserver env |
Incoming 502 | Bot not in room / Matrix error |
Chat REST 503 | MATRIX_JWT_SECRET, localpart map, user has Matrix identity |
No meeting.ended | LiveKit webhooks active? Room name = appointment id? Subscription enabled? |
Outgoing timeout / lastError | Is n8n reachable from Sparks server? TLS? |
12. Source code and further docs (app repo)
| Path in Vistameet-Teams | Content |
|---|---|
docs/N8N.md | Short overview |
docs/INCOMING_WEBHOOKS.md | Incoming → Matrix |
docs/openapi/sparks-automation-v1.yaml | OpenAPI 3.0 |
docs/API.md | Endpoint catalog |
server/routes/automation-api.ts | REST handlers |
server/lib/automation-webhooks.ts | Outgoing delivery |
server/routes/webhook-incoming.ts | Incoming |
n8n-nodes-sparks/ | Community nodes |
account/src/pages/AutomationWebhooksPage.tsx | Account UI |