Developer docs
Automations
Node graphs that run on a schedule — pull metrics, check a condition, build a report, run the AI marketer, call a webhook, send an email. Create them from code or let your assistant build them over MCP.
An automation is a small graph: one trigger, then data, logic, action and notify nodes wired together. The worker runs it on its schedule (or when you call /run), node by node, and keeps a run log with every node's output. Built-in examples: a weekly report by email, an ad-spend spike alert, a daily AI marketer check-up.
trigger.schedule ──▶ data.metrics ──▶ logic.condition ──true──▶ notify.email
(weekday 09:00) (yesterday) (spend_change > 30)Automations are different from apps (linear media pipelines) and from report schedules (one report, no logic).
Endpoints
All routes take an API key or an OAuth token; any workspace member may create, edit and run. Deleting needs the creator or an admin.
| Endpoint | Body / query → result |
|---|---|
GET / | AutomationDto[] — with issues[], nextRunAt, lastStatus, creditsThisMonth |
POST / | { workspaceId, name, graph, description?, settings?, enabled? } → AutomationDto. Saved even when incomplete; issues[] says what is missing |
GET / PATCH / DELETE / | PATCH takes any subset of the create body. enabled: true is refused (400 VALIDATION_ERROR, details.issues) while issues remain |
POST / | Run now → AutomationRunDto (QUEUED). 409 CONFLICT while a run is in flight; 429 past maxRunsPerDay |
GET / | paged AutomationRunDto (newest first) |
GET / | One run with steps[] — status, output and error per node |
Graph
{
"nodes": [
{ "id": "trigger", "type": "trigger.schedule", "x": 0, "y": 80, "config": { "cron": "weekday_09", "timezone": "Asia/Seoul" } },
{ "id": "metrics", "type": "data.metrics", "x": 280, "y": 80, "config": { "productId": null, "days": 1 } },
{ "id": "check", "type": "logic.condition", "x": 560, "y": 80, "config": { "field": "metrics.spend_change", "op": "gt", "value": 30 } },
{ "id": "email", "type": "notify.email", "x": 860, "y": 0, "config": { "to": ["me@company.com"], "subject": "[Poremu] Spend up {{metrics.spend_change}}%", "body": "{{metrics.periodEnd}}: ₩{{metrics.spend}} (CPA ₩{{metrics.cpa}}, ROAS {{metrics.roas}})" } }
],
"edges": [
{ "id": "e1", "from": "trigger", "to": "metrics" },
{ "id": "e2", "from": "metrics", "to": "check" },
{ "id": "e3", "from": "check", "to": "email", "port": "true" }
]
}Rules (checked by the server, reported in issues[]): exactly one trigger and nothing points into it; no cycles; every node reachable from the trigger; per-type config valid; at most 30 nodes and 60 edges; schedules at least 60 minutes apart; a valid IANA timezone; email recipients are workspace members only; webhook and product ids belong to the workspace. x / y are only for the canvas.
Nodes
| Node | Config | Output ({{key.field}}) | Credits |
|---|---|---|---|
trigger.schedule | cron — 5 fields or a preset: hourly, daily_09, weekday_09, weekly_mon_09, monthly_1_09; timezone | — | 0 |
trigger.manual | — (run with /run) | — | 0 |
data.metrics | productId?, days (period ending yesterday) | metrics.<metric>, metrics.<metric>_change (% vs the previous period), metrics.periodStart / periodEnd | 0 |
logic.condition | field (context path), op (gt gte lt lte eq neq contains exists), value | condition.result, condition.actual; outgoing edges use port: "true" / "false" | 0 |
action.report | productId?, days | report.id / title / url / shareUrl / summary | 5 |
action.agent | goal (templated), productId?, model? | agent.runId / text / approvals / proposals / credits | the run's charge (LLM + platform) |
action.webhook | webhookIds[] (workspace webhook endpoints), message | webhook.delivered / failed — sent as event automation.notify, Slack-shaped for Slack endpoints | 0 |
notify.email | to[], subject, body (templated, markdown) | email.sent / failed | 0 |
Metrics available: spend impressions clicks ctr cpc conversions cpa revenue roas installs signups purchases leads visits followers. Always available in templates: {{automation.name}}, {{automation.url}}, {{run.date}}, {{nodes.<id>.<field>}}.
Settings
| Field | Default | Meaning |
|---|---|---|
maxRunsPerDay | 48 | Scheduled + manual runs per rolling 24 h (max 48) |
maxCreditsPerRun | 5,000 | A node that would exceed this is not run; the run fails with LIMIT_REACHED |
maxCreditsPerMonth | 100,000 | Same, per calendar month (Asia/Seoul) for this automation |
notifyOnFailure[] | [] | Member emails told when a run fails |
pauseAfterFailures | 3 | Disable after this many failures in a row (0 = never) |
Scheduled runs charge the creator; manual runs charge the caller. Emails are capped at 200 per workspace per day across automations and report schedules.
Runs
schedule due, or POST /run → AutomationRun QUEUED (graph snapshot)
worker (5 s) → PROCESSING: nodes in topological order
a node runs iff an incoming edge comes from a SUCCEEDED node on the matching port; others are SKIPPED
node error → that step FAILED, the rest SKIPPED, run FAILED
end → SUCCEEDED | FAILED (+ failure email, failureStreak, auto-pause)
PROCESSING for 20 min → FAILED TIMEOUTsteps[] on a run: { nodeId, type, status: PENDING | RUNNING | SUCCEEDED | FAILED | SKIPPED, output?, error?, credits, startedAt, completedAt }. Realtime clients receive automation_run.updated on every step; outputs there are trimmed to 200 characters — fetch the run when it is terminal.
Example: create and run
curl https://api.poremu.ai/v1/automations \
-H "Authorization: Bearer $POREMU_API_KEY" -H "Content-Type: application/json" \
-d @spike-alert.json # { "workspaceId": "my-workspace", "name": "Spend spike", "graph": { … }, "enabled": true }
curl -X POST https://api.poremu.ai/v1/automations/AUTOMATION_ID/run \
-H "Authorization: Bearer $POREMU_API_KEY"
curl "https://api.poremu.ai/v1/automations/runs/RUN_ID" \
-H "Authorization: Bearer $POREMU_API_KEY"Over MCP
Your assistant can build these for you: automation_catalog returns the node specs, operators, presets, limits and the three templates; create_automation takes a graph (positions and edge ids optional) or a templateId — weekly-report-email, spend-spike-alert, daily-ai-checkup — with {{me}} recipients replaced by your address; update_automation turns it on; run_automation and list_automation_runs show results.
"Create an automation: every Monday 09:00 build last week's report for Lumo and email it to me and jay@lumo.app. Turn it on."