eroq

APIリファレンス · Platform

Flows

Chain renders, Clap's writing, posts and deliveries — start them by hand, by API, after a render, on a schedule or from a webhook (Zapier, Make, n8n).

GETPOSTPATCHDELETE/v1/flowsStudio plan or higher — each render a run makes is charged by its own endpoint

A flow is a graph of steps — renders, Clap's words, a post, a webhook, a folder — drawn in the studio's Flows editor or sent here as JSON. Every render a run makes goes through its own endpoint (images, videos, speech): same prices, same plan gates, same refunds; Clap's writing is included. Flows belong to the workspace: teammates share them.

Several ways to start one — a flow carries up to one trigger of each kind, each with its own line into the steps: trigger.manual (« When I run it »: the studio's Run, or POST /v1/flows/{id}/runs; it can ask for a prompt and a picture at every run), trigger.render (« After a render »: a render that names the flow with flow_id on POST /v1/images/generations, /v1/videos/generations, /v1/videos/edits or /v1/audio/speech, a run with inputs.creation_id, « Run a flow » on a creation — and, when its folderId is set, everything saved or moved into that folder), trigger.schedule (every day or week at at, read in the tz time zone), trigger.webhook (« When a webhook is called »: a secret URL any app can POST to, Zapier, Make, n8n, a form, a shop; see below). A run starts from ONE trigger and runs what its lines reach.

Runs happen on the server. POST /v1/flows/{id}/runs answers 202 with the run; poll GET /v1/flows/{id}/runs/{run_id} — every look moves the run on, and runs nobody watches are moved on every minute — or pass callback_url and the finished run is POSTed there once, in the flow.run.* event shape (see Webhooks; flow.run.stopped when someone stopped it). Each step reports its status, what it made (creationId and a fresh signed url), its text, its credits and, when it failed, error. A post is never sent by the API: the « Post to socials » step makes the run wait (status: "waiting", waiting names the clip, caption and platforms) until someone posts it — or lets it go — from the studio (TikTok and YouTube want a person's click per post); a post left waiting for 7 days is let go and the run carries on. POST …/runs/{run_id}/stop stops a run: steps not started are skipped, a render already sent still finishes and lands in the library.

The graph: nodes — { id, n, type, x, y, config }, where n is the step's number ({{#n}} inserts what step n wrote, or the link of what it rendered, into any text) — and edges — { from, to }, the ORDER (a step runs once every step leading to it is done). {{#n.field}} reads one field of a webhook's body ({{#1.customer.name}}). Types and their config: trigger.manual (askPrompt, askImage), trigger.render (kind: video · image · audio, folderId), trigger.schedule (every, at "HH:MM", day 0–6, tz), trigger.webhook (promptField: the field read as {{#1}}, empty = the whole body; imageField: a field holding an https picture; salt: a new value is a new URL), generate.image (prompt, model, aspect), generate.video (prompt, model, seconds, aspect, startFrom = an earlier image step), generate.voice (prompt = the words, model, voice), clap.write (instruction, about = an earlier step), publish.social (platforms, clip = an earlier clip step, caption), send.webhook (url, message — Discord and Slack show the message, other endpoints get the run as JSON), library.folder (folderId). The server re-sanitizes every graph it stores; send the one GET returns to keep what you do not change.

Plan, draft or published. Every plan builds flows. Running one, the studio's Run once included, and publishing it (published: true) come with the Studio plan or higher (403 plan_required below it). A draft runs only from the studio's editor; a published flow also starts by its schedule, its watched folder, flow_id, its webhook URL and POST /v1/flows/{id}/runs (a draft answers 409 flow_not_published there). Limits: 24 steps and 100 flows per workspace, 6 runs a minute per person, 50 automatic runs a day per flow (watched folder + schedule), 30 a minute and 500 a day from its webhook, the last 30 runs kept. A scheduled or webhook run runs as the person who made the flow, on the workspace's credits. A run that needs credits it does not have fails at that step with the endpoint's own 402 message.

The webhook URL (trigger.webhook): hookUrl on GET /v1/flows/{id}, https://eroq.ai/hooks/flows/{id}/{token}. No key: the URL is the key, keep it private (a new salt replaces it). POST any JSON, a form, or plain text (up to 64 KB): it is step #1, {{#1}} reads its promptField (or all of it), {{#1.field}} any field. It answers 202 { "ok": true, "run_id", "flow_id", "status": "running" }; 404 for an unknown or replaced URL, 409 flow_not_published, 403 plan_required, 429 with Retry-After, 400 content_blocked. A GET only describes the URL, so a link preview never starts a run. ?callback_url= (or an X-Eroq-Callback-Url header) gets the finished run. From Zapier: Webhooks by Zapier › POST; from Make: HTTP › Make a request; from n8n: the HTTP Request node.

エンドポイント

メソッドを選ぶと、そのリクエスト、プレイグラウンド、レスポンスが表示されます。

GET/v1/flows表示中

List the workspace's flows: their triggers, their chain, their last run, the next scheduled run and a run waiting on a post.

POST/v1/flows

Create a flow from a graph, a template, or blank, starting with the trigger you pick.

namestring

Up to 80 characters.

graphobject

{ nodes, edges } — see the notes. Sanitized: unknown steps, loops and lines into a trigger are dropped.

templatestring

Start from a template instead: caption-every-clip, clip-to-tiktok, daily-clip, still-to-reel, clip-to-discord, webhook-to-clip, scripted-voiceover.

triggerstring

Without graph or template: the trigger a blank flow starts with, manual (default), render, schedule or webhook.

tzstring

With trigger: "schedule": the IANA time zone its hour is read in. Default UTC.

publishedboolean

Put it online at once (its schedule, watched folder, webhook URL and API runs start it). Studio plan or higher. Default false: a draft.

GET/v1/flows/{id}

One flow — its graph, its webhook URL when it has the trigger — and its last 10 runs.

PATCH/v1/flows/{id}

Rename it, replace its graph, publish it or take it back to a draft. A run underway keeps the graph it started with.

namestring

New name, up to 80 characters.

graphobject

The whole graph, replaced (sanitized). Omit to keep it.

publishedboolean

Online (true, Studio plan or higher) or a draft (false, never refused).

DELETE/v1/flows/{id}

Delete the flow and its runs — everything it rendered stays in the library.

POST/v1/flows/{id}/runs

Run it now: 202 with the run, which moves on in the background — poll it. Refused (400) before anything is spent when a step is not set up or an input the trigger asks for is missing.

triggerstring

Where it starts: manual (default), render (needs inputs.creation_id), schedule (try a scheduled flow now), webhook (with inputs.payload).

inputsobject

prompt (asked by askPrompt, read as {{#1}}), creation_id (a creation of yours: the render to run on, or the picture askImage wants), image_url (an https picture, for askImage), payload (the body a « When a webhook is called » trigger reads, as if its URL had been called), locale (the language Clap writes in).

callback_urlstring

An https URL that gets the finished run, once, as a flow.run.* event body (Zapier callbacks, n8n's Wait node « On webhook call »).

GET/v1/flows/{id}/runs

The flow's runs, newest first (the last 30) — source says how each started: studio, api, attach, folder, schedule, webhook.

GET/v1/flows/{id}/runs/{run_id}

Where a run stands, step by step — looking moves it on. waiting names the post it waits on.

POST/v1/flows/{id}/runs/{run_id}/stop

Stop a run: steps not started are skipped, a post it waits on is let go; a render already sent still finishes (and is paid).

curl https://eroq.ai/v1/flows \
  -H "Authorization: Bearer $EROQ_API_KEY"
/v1/flows
→ GET /v1/flows
「例を実行」を押すと、ドキュメント自身のデータから実際のやり取りを再生します。キーもリクエストも不要で、料金もかかりません。

レスポンス

200 · application/json
{
  "object": "list",
  "flows": [{
    "id": "1e45…", "name": "Prompt to Discord",
    "triggers": ["trigger.manual"], "renderKind": null, "published": true, "nextRunAt": null,
    "steps": ["trigger.manual", "generate.video", "send.webhook"],
    "lastRun": { "status": "done", "at": "2026-10-02T14:05:00Z", "source": "api" }, "waiting": null
  }]
}