ClouisleClouisle

Embed Integration API

Agent chat and workflow execution endpoints for third-party websites and iframe embedding

The Embed Integration API enables embedding Clouisle Agent conversations and workflow executions into third-party portals, iframe widgets, or cookie-less client applications. The base path is /api/v1/embed.

Authentication & Security Policies

All embed endpoints exclusively require API Key authentication (prefixed with clou_). Cookie sessions are not accepted. Credentials can be passed using either of the following mechanisms:

  • Header: Authorization: Bearer clou_...
  • Query Parameter: ?token=clou_...

Resolution order is the token query parameter first, then the Authorization header; both must start with clou_, otherwise the request is treated as missing credentials and returns 401 (code 2000, embed_api_key_required).

Beyond authentication, the target must be usable for embedding: an Agent or Workflow must be in published status and have embed_config.enabled = true, otherwise the API returns 404 (agent_not_found / workflow_not_found) or 403 (embed_not_enabled).

Browser Embed Pages

Alongside the REST namespace, the product ships two pages you can drop straight into an <iframe> (these do not use the /api/v1 prefix):

PagePurposeQuery Parameters
/embed/agent/{agent_id}Full sign-in-free Agent chat UI (reuses the public chat page)token=clou_... (required), mode=fullscreen or bubble (default fullscreen)
/embed/workflow/{workflow_id}Workflow run UI (reuses the run-detail page)token=clou_... (required)
<iframe
  src="https://your-domain.com/embed/agent/550e8400-e29b-41d4-a716-446655440000?token=clou_xxx&mode=bubble"
  style="width: 420px; height: 640px; border: 0"
></iframe>

To avoid exposing the API key in the URL, the pages accept credentials over postMessage: after loading, the iframe posts { "type": "clouisle:ready" } to the parent, which replies with { "type": "clouisle:token", "token": "clou_..." }. The token query parameter still works as a fallback; with neither the Agent page stays in its loading state and the workflow page shows invalidToken.

The iframe also emits two events so the host page can react: { "type": "clouisle:conversation", "conversationId": "..." } when a conversation is created/switched, and { "type": "clouisle:close" } when the user clicks close.

Embed-mode limits: conversation history lives in browser localStorage (key clouisle:embed:history:agent:{agent_id}) rather than a login session, and message editing, regeneration, and version switching are unavailable in embed mode (the frontend disables them).

Domain Whitelist Verification (allowed_domains)

When an Agent or Workflow has allowed_domains configured in its embed_config:

  1. The server checks the Origin or Referer request header against the allowed domains list (supports wildcard subdomains such as *.example.com).
  2. If the request origin does not match the whitelist, the server returns 403 Forbidden (code: 3000, embed_domain_not_allowed).
  3. Direct requests with no origin header or items with empty whitelists are allowed.
  4. Workflow event streams (GET /workflows/runs/{run_id}/stream) are exempt from origin verification.

Agent Embed Endpoints

MethodPathDescription
GET/api/v1/embed/agents/{agent_id}/infoRetrieve public metadata, config, and variables for the embed widget
POST/api/v1/embed/agents/{agent_id}/chat/streamStream chat message via Server-Sent Events (SSE)
POST/api/v1/embed/agents/{agent_id}/chat/runsCreate a durable async Agent run (returns 202 Accepted)
GET/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/streamSubscribe to replay and live SSE events of a durable run
GET/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}Query durable run status
GET/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/eventsReplay buffered run events by sequence
POST/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/inputsSend steering or follow-up inputs during execution
POST/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/answersSubmit structured answers required by ask_user tool calls
POST/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stopCollaboratively terminate an active run
GET/api/v1/embed/agents/{agent_id}/conversations/{conversation_id}/messagesGet message history of an embed conversation
POST/api/v1/embed/agents/{agent_id}/upload/fileUpload attachment files for embed sessions

1. Get Embed Agent Info

GET /api/v1/embed/agents/{agent_id}/info HTTP/1.1
Authorization: Bearer clou_api_key

Response (200 OK)

{
  "code": 0,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Support Assistant",
    "description": "Answers customer questions regarding returns and billing",
    "icon": "🤖",
    "avatar_url": null,
    "opening_message": "Hello! How can I assist you today?",
    "suggested_questions": [
      "How do I request a refund?",
      "Where can I find my invoice?"
    ],
    "variables": [],
    "enable_attachments": true,
    "attachment_config": {
      "max_file_count": 5,
      "max_file_size_mb": 10
    },
    "hide_tool_calls": false,
    "hide_message_actions": false,
    "hide_reasoning": false,
    "embed_config": {
      "enabled": true,
      "allowed_domains": ["https://example.com"]
    }
  },
  "msg": "success"
}

2. Stream Chat Message

POST /api/v1/embed/agents/{agent_id}/chat/stream HTTP/1.1
Authorization: Bearer clou_api_key
Content-Type: application/json

{
  "message": "What is the return window?",
  "conversation_id": "conv-uuid-optional",
  "variables": {}
}

Returns a text/event-stream SSE response whose events are identical to the main chat stream endpoint (message_start, content_delta, rag_start/rag_context, reasoning_start/reasoning_delta/reasoning_end, tool_call/tool_result, media_result, compression_start/compression_end, output_truncated, iteration_cap_reached, message_end, error) — see SSE Streaming Events.

3. Create Durable Run

For disconnected resilience and long-running tools, use the durable run workflow:

POST /api/v1/embed/agents/{agent_id}/chat/runs HTTP/1.1
Authorization: Bearer clou_api_key
Content-Type: application/json

{
  "message": "Generate Q3 sales analysis",
  "conversation_id": null,
  "variables": {}
}

Response (202 Accepted)

{
  "code": 0,
  "data": {
    "run_id": "run-uuid-1234",
    "conversation_id": "conv-uuid-5678",
    "status": "queued",
    "stream_url": "/embed/agents/550e8400-e29b-41d4-a716-446655440000/chat/runs/run-uuid-1234/stream"
  },
  "msg": "success"
}

Clients subscribe to GET /api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stream?after_sequence=N to stream events with deduplication and reconnection capability.

4. Run Control and Query Parameters

MethodPathQuery Parameters / Body
GET/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/streamafter_sequence (default 0; negative clamped to 0) — replays buffered events with a higher sequence, then follows the live stream
GET/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/eventsafter_sequence (default 0) — non-streaming read of buffered events
GET/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}none — returns RunOut (status, error_code, pending_tool_*, …)
POST/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/inputsJSON: delivery (steer/follow_up/auto, default auto), content, attachments, request_id (idempotency key)
POST/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/answersJSON: tool_call_id (required), answers (ID → answer), skipped
POST/api/v1/embed/agents/{agent_id}/chat/runs/{run_id}/stopno body — cooperatively stops the run; the stream then receives run_end with status: "stopped"
GET/api/v1/embed/agents/{agent_id}/conversations/{conversation_id}/messagesnone — returns the conversation's visible messages (each with version_count); the conversation must belong to the API key's user, otherwise 404 (6210)
POST/api/v1/embed/agents/{agent_id}/upload/filemultipart/form-data with field name file and query parameter category (default documents)

Run status values, the single run_end, and the resumption strategy are the same as the main chat API — see Durable Runs and Control in the Agent Chat API and SSE Streaming Events.


Workflow Embed Endpoints

MethodPathDescription
GET/api/v1/embed/workflows/{workflow_id}/infoRetrieve workflow embed details and input schema
POST/api/v1/embed/workflows/{workflow_id}/runExecute an embedded workflow
GET/api/v1/embed/workflows/runs/{run_id}/streamStream workflow node execution progress via SSE

1. Run Workflow

POST /api/v1/embed/workflows/{workflow_id}/run HTTP/1.1
Authorization: Bearer clou_api_key
Content-Type: application/json

{
  "inputs": {
    "query": "Summarize customer feedback",
    "format": "markdown"
  }
}

Response (200 OK)

{
  "code": 0,
  "data": {
    "run_id": "wf-run-uuid-1234",
    "stream_url": "/api/v1/workflows/runs/wf-run-uuid-1234/stream"
  },
  "msg": "success"
}

The returned stream_url points at the main workflow stream route (/api/v1/workflows/runs/{run_id}/stream), which targets signed-in sessions; embed clients should instead subscribe to GET /api/v1/embed/workflows/runs/{run_id}/stream?from_sequence=N.

2. Stream Workflow Run Progress

GET /api/v1/embed/workflows/runs/{run_id}/stream?from_sequence=0
ParameterTypeRequiredDefaultDescription
from_sequenceintegerNo0Replay events after this sequence, then follow live events; used to resume after a disconnect

Note the naming difference from Agent runs: workflow streams use from_sequence, Agent runs use after_sequence. This route does not perform the domain whitelist check (every other workflow embed endpoint does), but it does require the run to have been triggered by the API key's user, otherwise it returns 404 (workflow_run_not_found).

3. Workflow Embed Info

GET /api/v1/embed/workflows/{workflow_id}/info

Returns id, name, description, icon, variables (input parameter definitions), and embed_config. The workflow must be published with embedding enabled, otherwise the call returns 404 (workflow_not_found) or 403 (embed_not_enabled).


Error Codes

Error CodeIdentifierDescription
2000UNAUTHORIZEDMissing API key, credentials without the clou_ prefix, or an invalid/expired key (embed_api_key_required)
3000PERMISSION_DENIEDEmbedding not enabled (embed_not_enabled), or the request origin is not in allowed_domains (embed_domain_not_allowed)
4000NOT_FOUNDWorkflow does not exist or is not published (workflow_not_found); workflow run does not exist or was not triggered by this API key's user (workflow_run_not_found)
6200AGENT_NOT_FOUNDAgent does not exist or is not published (agent_not_found)
6210CONVERSATION_NOT_FOUNDConversation does not exist or does not belong to the API key's user

How is this guide?

On this page