cap-n8n
Maps CAP onto n8n: a programmatic workflow API, @n8n.trigger annotations dispatched through the transactional outbox, and a typed cds import --from n8n.
Facts
Where it sits
Who is behind it
In the atlas: maintains 6, contributes to 5, wrote 1@sleibachmaintainer
Before choosing this
Conditions
LicenceSAP Developer License Agreement 3.2 CAP§ 1, 2, 3A cds-plugin is used with SAP CAP materials, or an artifact is explicitly identified as a CAP plugin or application.
- § 1 License. Productive customer applications are limited to SAP BTP or another SAP-licensed platform, and mass extraction to a non-SAP product is restricted except where solely required for SAP interoperability.
- § 2 Intellectual Property. The agreement retains SAP's rights in the covered materials and limits making APIs, tools or software available to third parties, while preserving ownership of customer applications subject to SAP's underlying rights.
- § 3 Artificial Intelligence Training. The agreement prohibits use of the covered materials and customer applications for training artificial-intelligence models or systems.
What it declares
Every artifact
- Type
- CDS plugin
- Origin
- Independently maintained
- Runtime
- Node.js
As a CDS plugin
- Declared for
- >=8.0
- Distributed through
- npm
Connections
Triggers n8n workflows from a CAP application
Driving an external workflow engine and reacting to what it emits
Download
Install
npm add cap-n8nDerived from the package name. No recipe recorded; the README has the configuration.
README
quoted from sleibach/cap-n8n under Apache-2.0, readcap-n8n
A SAP CAP plugin that maps the @cap-js/process shape onto
n8n: a programmatic Workflow API, @n8n.trigger annotations routed
through the transactional outbox, and a typed cds import --from n8n.
The only thing you need to provide is an n8n service key (a base URL + API key from any n8n instance). Everything else — seeding workflows, activating, triggering, polling executions, asserting — runs autonomously.
At a glance
Annotations — fire n8n webhooks on lifecycle events, after commit, via the transactional outbox:
@n8n.trigger: 'book-ordered' // CREATE + UPDATE
entity Orders as projection on my.Orders;
@n8n.trigger: { workflow: 'book-saved', on: ['SAVE'] } // CRUD + Fiori draft events
@odata.draft.enabled entity Books as projection on my.Books;
Programmatic API — drive workflows from your handlers:
const n8n = await cds.connect.to('n8n')
await n8n.trigger('book-ordered', { book: 'Moby Dick' }) // POST /webhook/:path
const execs = await n8n.listExecutions(workflowId) // poll & assert results
Typed import — turn a workflow into a typed CDS service:
cds import workflow.json --from n8n
# → action trigger(book: String, quantity: Integer) returns { executionId: String };
Console mode in development (no n8n needed), .env or BTP destination otherwise.
Getting started — the sample app
test/bookshop is the reference application: a minimal bookshop
showing every feature (all annotation forms, draft events, bound actions, the typed
import, and the test setup). It runs without any n8n instance:
npm install && npm run build
cd test/bookshop
npm run watch # console mode — triggers are logged, no n8n needed
npm run watch:live # real mode — needs an n8n service key in .env (see .env.example)
Start there: test/bookshop/README.md walks through
firing each trigger with curl and using the app as a template for your own project.
Install
npm add cap-n8n
Configure connectivity
Local development — drop the service key into a .env file (gitignored):
N8N_BASE_URL=https://your-instance.app.n8n.cloud
N8N_API_KEY=eyJ...your-api-key...
By default the plugin runs in console mode (kind: n8n-console): triggers are logged
and a synthetic executionId is returned, so the app runs with no instance at all. To talk
to a real instance locally, run with the REST kind, e.g.:
cds watch --profile hybrid # or set requires.n8n.kind = 'n8n-rest'
Production (BTP) — user-provided service (simplest) — create and bind a
user-provided service instance carrying the service key. CAP merges its credentials
into cds.requires.n8n.credentials automatically:
cf create-user-provided-service n8n -p '{"baseUrl":"https://your.n8n.cloud","apiKey":"eyJ..."}'
cf bind-service <your-app> n8n
If the instance has a different name, point CAP at it from your app config:
{ "cds": { "requires": { "n8n": { "vcap": { "name": "my-n8n" } } } } }
Production / hybrid (BTP) — destination — alternatively bind a destination named
n8n. Put the base URL in the destination URL and the API key in the additional
property URL.headers.X-N8N-API-KEY. The plugin resolves it via
@sap-cloud-sdk/connectivity, exactly like @cap-js/notifications.
Inline credentials — you can also put credentials directly in your app config and
keep the secret in an environment variable via the env: indirection:
{
"cds": {
"requires": {
"n8n": {
"credentials": { "baseUrl": "https://your.n8n.cloud", "apiKey": "env:N8N_API_KEY" }
}
}
}
}
Resolution order: bound/inline credentials (incl. cds bind in hybrid mode) →
BTP destination → N8N_BASE_URL/N8N_API_KEY environment variables.
Programmatic API
const n8n = await cds.connect.to('n8n')
await n8n.trigger('book-ordered', { book: 'Moby Dick', buyer: 'a@b.com' }) // POST /webhook/:path
await n8n.activate(workflowId) // POST /api/v1/workflows/:id/activate
await n8n.deactivate(workflowId) // POST /api/v1/workflows/:id/deactivate
await n8n.listExecutions(workflowId) // GET /api/v1/executions?workflowId=
await n8n.getExecution(executionId) // GET /api/v1/executions/:id?includeData=true
await n8n.createWorkflow(json) // POST /api/v1/workflows (seed helper)
Annotations
Annotate an entity or event with the n8n production-webhook path. After the surrounding
transaction commits, the payload is POSTed to {baseUrl}/webhook/<path>, routed through
the CAP transactional outbox for resilience:
// string shorthand — fires on CREATE and UPDATE
@n8n.trigger: 'book-ordered'
entity Orders as projection on my.Orders;
// record form — pick the lifecycle events explicitly
@n8n.trigger: { workflow: 'book-archived', on: ['DELETE'] }
entity Books as projection on my.Books;
// Fiori draft-enabled entities: draft lifecycle events are supported
@odata.draft.enabled
@n8n.trigger: { workflow: 'book-saved', on: ['SAVE'] }
entity Books as projection on my.Books actions {
// bound actions fire when called (on the active or the draft row)
@n8n.trigger: 'book-archived'
action archive();
};
// unbound actions/functions and custom events work too
event OrderShipped @(n8n.trigger: 'order-shipped') { orderId: UUID; }
Supported on events (entities):
| Event | Fires | Payload |
|---|---|---|
CREATE / UPDATE | row written (incl. draft activation) | the resulting row |
DELETE | row deleted | the deleted row's keys |
SAVE | draft activated (Fiori "Save") — on non-draft entities = CREATE+UPDATE shortcut | the activated data |
EDIT | user starts editing (draft created from active row) | the row being edited |
NEW / PATCH / DISCARD | draft created / field changed / discarded | the draft data |
NEW/PATCH/SAVE/EDIT/DISCARD require @odata.draft.enabled (CANCEL is accepted
as the legacy alias for DISCARD). Bound-action payloads are the bound row's keys merged
with the action parameters; unbound actions send the call parameters.
Typed import
cds import workflow.json --from n8n
Generates a typed CDS service with a trigger action. The input contract is derived, most
reliable first:
- A node named
CAP Input Schemaholding a JSON Schema (recommended convention). - The webhook node's declared body fields.
- Pinned/sample data (
*.sample.jsonor the node'spinData). - Fallback: a single
body : LargeStringpassthrough.
Tests
npm test
- The console integration suite always runs (no key needed).
- The REST integration suite runs the live seed → activate → trigger → poll → assert
loop and skips gracefully unless
N8N_BASE_URL+N8N_API_KEYare set. - For CI, run an
n8nio/n8ncontainer and pointN8N_BASE_URLat it.
License
Apache-2.0
History
v0.1.0
Others providing
Compare all 4 on the Workflow integration page →- @cap-js/n8n@cap-js/n8nTriggers n8n workflows from a CAP application through @n8n.process.start annotations or a programmatic n8n service, resolving credentials from local config, a Cloud Foundry binding or a BTP destination.sap official, capTriggers n8n workflows from a CAP application
- com.sap.cds:cds-feature-n8ncom.sap.cds:cds-feature-n8nTriggers n8n workflows from a CAP Java application through @n8n.process.start annotations or a programmatic N8nService, delivered by webhook calls through the CAP outbox.sap official, capTriggers n8n workflows from CAP Java through the outbox
- @cap-js/n8n@cap-js/n8nTriggers n8n workflows from a CAP application through @n8n.process.start annotations or a programmatic n8n service, resolving credentials from local config, a Cloud Foundry binding or a BTP destination.sap official, capTriggers n8n workflows from a CAP application
- @cap-js/process@cap-js/processStarts, cancels, suspends and resumes SAP Build Process Automation processes from a CAP service through entity annotations, or through a typed CDS service imported from the process definition.sap official, capStarts and manages SAP Build Process Automation processes from CAP
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
History in the atlas
- First seen.
For your agent
- Ref
artifact:sleibach-cap-n8n- JSON
- /artifacts/sleibach-cap-n8n.json
- MCP
- Connecting an agent