Confluye
Endpoints

End users

Run workflows for your product's customers, poll and cancel their runs, request website login links, and erase a customer.

These routes let a product act for its own customers (end users). They exist only while the deployment runs with FLUXUS_END_USERS=true; see End users and memory for the concepts.

Product gateway key

Every route on this page requires a product gateway key (scope: "end_user_gateway"), sent as Authorization: Bearer hise_…. An Admin or Owner creates it with the session endpoint POST /api/api-keys:

{
  "workspaceId": "ws_123",
  "name": "Telegram bot",
  "scope": "end_user_gateway",
  "allowedWorkflowIds": ["wf_abc"]
}

allowedWorkflowIds must list at least one workflow of that workspace. The scope and the allowlist are fixed at creation; to change them, create a new key and revoke the old one. A product gateway key:

  • runs only its allowed workflows, and only for an end user;
  • reads a run only through the gateway status route below, only for runs it started, and only for the end user that owns the run;
  • is refused (403) by every other v1 route and by the MCP endpoints;
  • stops working when its creator loses explicit workspace access, and while end users are disabled (403).

A product may create at most 60 new end users per key per minute; the next call answers 429 with Retry-After.

Endpoints

MethodPathDescription
POST/api/v1/workflows/{id}/executeRun an allowed workflow for an end user (queued)
GET/api/v1/end-users/runs/{id}Status and outcome of one of the key's runs
DELETE/api/v1/end-users/runs/{id}Cancel one of the key's runs
POST/api/v1/runs/{id}/rerunRe-run one of the key's runs for the same end user
POST/api/v1/end-users/connect-requestsOne-use website login link for an end user and a site
GET/api/v1/end-users/connect-requests/{id}Poll whether the customer saved that new login
POST/api/v1/end-users/erasuresErase everything stored for an end user
GET/api/v1/end-users/erasures?id={id}Poll an erasure

End user IDs

endUser.externalId is the ID your product uses for the customer: 1–128 characters of letters, digits, and . _ - : @ | + =. Routes that do not take a JSON body read it from the X-End-User-Id header, so it never appears in a URL. Treat it as customer data: Confluye never writes it to audit events or logs.

Run a workflow for an end user

POST /api/v1/workflows/{id}/execute

{
  "endUser": { "externalId": "tg-12345" },
  "message": "Switch the form to the buyer I mentioned",
  "input": { "prompt": "Switch the form to the buyer I mentioned" }
}
FieldRequiredDescription
endUser.externalIdYesThe customer the run acts for. A new ID creates the end user.
messageYesThe customer's message, 1–32,000 characters and not blank. With the reply block's output it forms the turn recorded in memory.
inputNoThe workflow input, as for any execution. Pass the message here too when blocks read it from input.

The end user is the identity of the run, not part of input: a block or a model cannot change it, and an endUserId field inside input is ignored. End user runs always execute the active version: dryRun: true or target: "candidate" answers 400, and so does a missing or blank message. Idempotency-Key is supported and covers endUser, message, and input: repeating a key with a different message answers 409 (code: "idempotency_replay_mismatch") instead of replaying the earlier run. A stored receipt belongs to that end user, so an erased customer's key is never replayed for a new customer with the same ID.

202 — the run was queued:

{
  "run": {
    "id": "run_1",
    "workflowId": "wf_abc",
    "status": "queued",
    "startedAt": "…",
    "finishedAt": null,
    "durationMs": null
  },
  "queued": true,
  "status": "queued",
  "active": true,
  "pollAfterMs": 1000,
  "links": {
    "self": "/api/v1/end-users/runs/run_1",
    "cancel": "/api/v1/end-users/runs/run_1"
  },
  "statusUrl": "/api/v1/end-users/runs/run_1",
  "cancelUrl": "/api/v1/end-users/runs/run_1",
  "cancelMethod": "DELETE"
}

Start and rerun receipts include the same safe outcome fields as polling: status, active, pollAfterMs, and output, error, or connectionRequired when available. They never include inputs, steps or logs.

An occupied Claude Code or Codex credential does not delay acceptance of an end user run. The worker checks the CLI login before execution, so an accepted run can still fail if that login is unavailable. Poll the returned run ID to follow its outcome.

Runs of one end user start in the order they were sent; each waits until the previous turn recorded its reply. A turn that parks on an approval or a timer releases the order: the next run starts and sees the parked message as pending.

Poll or cancel a run

GET /api/v1/end-users/runs/{id} and DELETE /api/v1/end-users/runs/{id}, both with the X-End-User-Id header. A run is visible only when its ID, the key that started it, and its end user all match, and that end user is not being erased; otherwise the answer is 404. Runs of an erased end user are never visible, even after the same external ID starts a new end user.

{
  "run": {
    "id": "run_1",
    "workflowId": "wf_abc",
    "status": "succeeded",
    "startedAt": "…",
    "finishedAt": "…",
    "durationMs": 5120
  },
  "status": "succeeded",
  "queued": false,
  "active": false,
  "output": { "answer": "…" },
  "error": null,
  "links": { "self": "/api/v1/end-users/runs/run_1", "cancel": "/api/v1/end-users/runs/run_1" },
  "cancelMethod": "DELETE",
  "pollAfterMs": null
}

Keep polling while active is true (queued, running, or waiting), after pollAfterMs. The response never contains the workflow definition, steps, or logs. DELETE cancels a queued, running, or waiting run and returns the same shape; cancelling a finished run answers 409, and cancelling an already cancelled run returns it unchanged. Every response of these routes, including 400, 401, 403, and 404 answers, is Cache-Control: no-store with Vary: Authorization, X-End-User-Id.

Website login required

When a block needs the customer's website login and it is not usable, the run ends failed without retries and the status response carries:

{ "connectionRequired": { "reason": "expired", "siteKey": "centris" } }
reasonMeaningNew login link?
missingThe customer never signed in to this siteYes
expiredThe saved login needs the customer to sign in againYes
rejectedThe website rejected the saved loginYes
revokedThe previous saved login was disconnectedYes, with a fresh login and save
grant_missingA workspace Admin or Owner has not authorized this block for the siteNo

For missing, expired, rejected, and revoked, your product can request a new link automatically when the customer asks for something requiring that website. Keep the original request, send the link, and wait for the customer to sign in and save access before sending the turn again. The previous login stays unusable; issuing a link never restores it. grant_missing requires authorization from a workspace Admin or Owner.

Re-run

POST /api/v1/runs/{id}/rerun with the X-End-User-Id header re-runs one of the key's runs for the same end user. 201 returns the safe outcome projection plus statusUrl, cancelUrl, and cancelMethod. A run of another key or end user answers 404; a run whose end user was erased answers 409, and one whose end user is being erased answers 409 with code: "erasing" and Retry-After.

POST /api/v1/end-users/connect-requests

{ "endUser": { "externalId": "tg-12345" }, "siteKey": "centris" }

201 — { "requestId": "…", "connectUrl": "https://…", "expiresAt": "…" }. Send connectUrl to the customer; it works once and expires after 15 minutes. It signs the customer in to that website only and never grants a Confluye session. A new link cancels the customer's previous link for the same site. Responses are Cache-Control: no-store and are never replayed from an idempotency cache.

Poll GET /api/v1/end-users/connect-requests/{requestId} with X-End-User-Id set to the same external ID. 200 returns only { "requestId": "…", "status": "pending" | "connected" | "expired" | "cancelled" }. connected means the customer saved this request's login and it is still usable. A completed request whose login was disconnected or replaced cannot continue the action. Requests outside the key owner's workspace, for another customer, or without a live website grant on a workflow allowed by the key answer 404. Responses are Cache-Control: no-store with Vary: Authorization, X-End-User-Id; they contain no login link, browser state, or connection ID. Polling creates no customer or connection and does not consume the link.

Use a durable Wait between polls and a bounded deadline, such as 15 minutes. On connected, submit the retained customer request once and poll that new run. On cancellation or expiry, stop and explain that sign-in was not completed. The platform does not automatically retry the original failed run or reconnect a revoked workflow grant.

Erase an end user

POST /api/v1/end-users/erasures

{ "endUser": { "externalId": "tg-12345" } }

202 — the erasure started, or was already running or finished (repeating the request is safe):

{
  "erasure": { "id": "eu_1", "status": "erasing" },
  "links": { "self": "/api/v1/end-users/erasures?id=eu_1" },
  "pollAfterMs": 2000
}

Poll GET /api/v1/end-users/erasures?id={id} until status is erased (pollAfterMs is then null). Erasure cancels the customer's open runs and deletes their conversation, memory, work in progress, pending site notes, and website logins in every workflow of the workspace. From the moment it starts, a new run for the same ID answers 409 with Retry-After. Once it finishes, the same ID starts a new end user with no history. While the erasure waits for a website login to be deleted at the browser provider, the erasure object includes pendingReason: "browser_revocation"; keep polling.

Errors

StatusWhen
400Invalid JSON or fields; missing endUser.externalId; missing or blank message on an end user run; invalid ID (code: "invalid_external_id"); endUser or message sent with another kind of key; dryRun or candidate on an end user run; missing or invalid X-End-User-Id; missing erasure id
401Missing, unknown, or revoked bearer token
403Not a product gateway key ("A product gateway credential is required."); workflow not on the key's allowlist, end users disabled, or the creator lost workspace access ("A workspace API key is required.")
404Run not found for this key and end user; site not granted to any allowed workflow (code: "site_not_found"); end user or erasure not found (code: "end_user_not_found")
409An Idempotency-Key reused with a different body, such as another message (code: "idempotency_replay_mismatch"); the end user is being erased (code: "erasing", Retry-After: 5); cancelling a finished run; re-running an erased customer's run; the customer is already signed in (code: "connection_ready")
429Too many new end users for this key (code: "rate_limited", Retry-After: 60)
503The workflow queue is not configured (end user runs are always queued); website connections are unavailable; erasure needs the queue while the customer has runs in flight, or extraction/compaction is still active (code: "erasure_unavailable"). Retry erasure after the memory jobs finish.

Next steps