Headless API

The custom chat interface lets you connect your genie to any application you build and control. Your application talks to your genie directly over a REST API, called a Headless API, instead of routing users through Slack, Microsoft Teams, or Workato GO. The custom chat interface includes API endpoints to manage conversations and send and receive genie messages. This API is separate from the Agent Studio Developer API, which lets you create, configure, and maintain genies.

HEADLESS API ENDPOINTS REQUIRE A CUSTOM CHAT INTERFACE

Headless API endpoints are only compatible with the custom chat interface option.

PRIVATE BETA

Headless APIs are in private beta and only available to selected customers. Contact your Customer Success Manager to learn more.

Headless API prerequisites

Headless API has the following prerequisites:

  • A client role with the following permissions:
    • Genies: Read and write permissions for CRUD operations on genies, skills, knowledge bases, user groups, and guardrails
    • Genie client: Read and write permissions for CRUD operations on clients and client-genie assignments
  • An API client attached to the preceding client role
  • A folder ID where the genie is stored. Use the following API endpoint to obtain your folder ID:
curl
curl -s "https://app.workato.com/api/folders" \
  -H "Authorization: Bearer $DEV_API_TOKEN"

Headless API base URLs

Headless API is available in all data centers where Agentic is supported. The base URLs follow the same per-data-center scheme as the app host. For example:

Data centerDev API base URLHeadless API base URL
UShttps://www.workato.comhttps://genie-api.workato.com

Refer to the data center overview for more information.

Authentication

The Headless API provides two access methods that address different integration scenarios. Authentication is enforced at the API gateway layer, with no runtime dependency on the Workato system. Token configuration is synced to the gateway asynchronously and verification is performed in-process. API tokens are per-environment. This means you must have a unique API token for each environment. Refer to How to generate an API token for more information.

Headless API supports the following access methods:

API key:

http
Authorization: Bearer <api_key>
X-IDP-User-Id: <idp_user_id>

OAuth 2.0 (PKCE):

http
Authorization: Bearer <access_token>

Authorization methods comparison

Refer to the following authorization method comparison and use case recommendation tables to determine which authorization method to use:

Comparison pointAPI key (token-based)OAuth 2.0 (PKCE)
How it worksThe builder's backend holds a static API key and asserts user identity through the X-IDP-User-Id header.End users authenticate directly through Workato Identity and delegate to the customer's IdP through SAML SSO.
End user visibilityWorkato is invisible to end users.End users see an IdP login step.
Required headersAuthorization: Bearer <api_key> and X-IDP-User-Id: <idp_user_id>Authorization: Bearer <access_token>
Client credentialsThe API key is static and is shown only once.client_id only — PKCE replaces the client secret.
User identity managed byThe builder maps user IDs to Workato IdP user IDs.IdP directly, such as Okta, Azure AD, OneLogin, and more.
PrerequisitesEnd users provisioned in Workato Identity through IAM API or the Workato UI.One-time SAML federation between Workato Identity and the customer's existing IdP. Workato Identity acts as a broker. It doesn't replace the customer's IdP.
Best forServer-side integrations, QA, automated testing, internal tools.User-facing apps requiring SSO, centralized access governance, and per-user permissions.
ScenarioRecommended
QA / automated testingAPI key
Security red-teaming through CI/CDAPI key
Internal tool with builder-controlled authorizationAPI key
Custom chat UI where Workato should be invisibleAPI key
Employee portal with company SSOOAuth 2.0
Multi-tenant app serving multiple organizationsOAuth 2.0
Deployment requiring IdP-governed access controlOAuth 2.0
Mobile or single-page app or public clientOAuth 2.0

Quick reference

TypeResourceDescription
GET/api/v1/genies/:genie_handle/chat/conversationsList a user's conversations.
POST/api/v1/genies/:genie_handle/chat/conversationsCreate a new conversation.
GET/api/v1/genies/:genie_handle/chat/conversations/
:conversation_id
Get conversation details and state.
GET/api/v1/genies/:genie_handle/chat/conversations/
:conversation_id/messages
Get message history for a conversation.
POST/api/v1/genies/:genie_handle/chat/conversations/
:conversation_id/messages
Send a message and receive a streaming response.
GET/api/v1/genies/:genie_handle/chat/conversations/
:conversation_id/genie-runs/:genie_run_id
Reconnect to a message stream.
GET/api/v1/genies/:genie_handle/chat/
conversations/events
Get recent events.
POST/api/v1/genies/:genie_handle/chat/conversations/
:conversation_id/skill_approval/:call_id
Approve or reject a skill confirmation.
POST/api/v1/genies/:genie_handle/chat/
runtime_connection/:runtime_connection_attempt_id/link
Get an authentication link for a runtime connection.
POST/api/v1/genies/:genie_handle/chat/
runtime_connection/:runtime_connection_attempt_id/reject
Reject a runtime connection request.
POST/api/v1/genies/:genie_handle/chat/conversations/
:conversation_id/upload
Upload a file for attachment to a message.

List conversations

Retrieve a list of the authenticated user's conversations. Results are listed by the created_at timestamp in descending order.

bash
GET /api/v1/genies/:genie_handle/chat/conversations

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.

Query parameters

NameTypeDescription
limitinteger
optional
Number of conversations to return. Defaults to 50.
cursorstring
optional
Pagination cursor from a previous response.

Response

NameTypeDescription
list[]arrayList of conversations.
list[].conversation_idstringConversation ID.
list[].topicstringConversation topic.
list[].last_updated_atstringTimestamp of the last update.
list[].created_atstringTimestamp when the conversation was created.
total_countintegerTotal number of conversations.
cursorstringCursor for the next page of results.

Create a conversation

Create a new conversation with the genie.

bash
POST /api/v1/genies/:genie_handle/chat/conversations

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.

Response

NameTypeDescription
conversation_idstringID of the new conversation.

Get a conversation

Retrieve the details and current state of a conversation.

bash
GET /api/v1/genies/:genie_handle/chat/conversations/:conversation_id

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
conversation_idstring
required
Conversation ID.

Response

NameTypeDescription
updated_atstringTimestamp of the last update.
statestringCurrent state of the conversation. One of idle, ai_running, skill_processing, or awaiting_approval.
last_eventobjectThe most recent event in the conversation.

Get messages

Retrieve message history for a conversation. Results are listed by the created_at timestamp in descending order.

bash
GET /api/v1/genies/:genie_handle/chat/conversations/:conversation_id/messages

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
conversation_idstring
required
Conversation ID.

Query parameters

NameTypeDescription
cursorstring
optional
Pagination cursor from a previous response.
limitinteger
optional
Number of messages to return. Defaults to 100.

Response

NameTypeDescription
conversation_idstringConversation ID.
messages[]arrayList of messages.
messages[].message_idstringMessage ID.
messages[].sourcestringMessage origin. One of user or genie.
messages[].contentstringText content of the message.
messages[].genie_run_idstringID of the request/response cycle the message belongs to.
messages[].created_atstringTimestamp of the message in RFC3339 format.
total_countintegerTotal number of messages in the conversation.
cursorstringCursor for the next page of results.

Send a message

Send a user message and receive a real-time stream of events as the genie processes and responds.

bash
POST /api/v1/genies/:genie_handle/chat/conversations/:conversation_id/messages

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
conversation_idstring
required
Conversation ID.

Payload

NameTypeDescription
messagestring
required
The user's message. Maximum 12 KB.
file_idstring
optional
ID of a previously uploaded file to attach to this message.
streamboolean
optional
Set to true to receive an SSE stream in the response. Defaults to false.

Response

When stream is false, returns HTTP 202 with the following body:

NameTypeDescription
conversation_idstringConversation ID.
genie_run_idstringID of the genie run. Use this to reconnect to the stream.

When stream is true, the response is a stream of Server-Sent Events. The stream closes when the genie finishes processing, indicated by the processing.finished event.


Reconnect to a stream

Reopen the SSE stream for a specific genie run. Use this to recover events after a disconnection. Pass the ID of the last successfully received event in the Last-Event-ID header.

bash
GET /api/v1/genies/:genie_handle/chat/conversations/:conversation_id/genie-runs/:genie_run_id

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
conversation_idstring
required
Conversation ID.
genie_run_idstring
required
Genie run ID, as returned by Send a message.

Headers

NameTypeDescription
Last-Event-IDstring
optional
ID of the last successfully received event. The stream replays events from this point.

Response

The response is a stream of Server-Sent Events.


Get events

Retrieve recent events. Use this as a fallback to manually fetch missed events after a disconnection. Events are returned oldest first and are available for 24 hours.

bash
GET /api/v1/genies/:genie_handle/chat/conversations/events

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.

Query parameters

NameTypeDescription
since_created_atstring
optional
Lower bound (inclusive) on event creation time, as an RFC3339 timestamp (for example, 2026-05-26T12:00:00.123456Z). Pass next_since_created_at from the previous response to fetch the next page.
conversation_idstring
optional
Filter events by conversation ID.
limitinteger
optional
Page size. Defaults to 100.

Response

NameTypeDescription
events[]arrayArray of events, ordered oldest first.
events[].conversation_idstringConversation ID.
events[].genie_handlestringGenie handle (string identifier, for example gin-AaDX9axF-CNtgQn-B6).
events[].genie_run_idstringID of the genie run this event belongs to.
events[].typestringEvent type.
events[].event_idstringUUIDv7 identifying this event.
events[].seq_numintegerPer-genie-run monotonic sequence number.
events[].created_atstringGateway-side timestamp when the event was persisted, in RFC3339 format.
next_since_created_atstringContinuation cursor. When present, pass this value as since_created_at on the next request to fetch the next page.

Approve or reject a skill

Approve or reject a skill confirmation request. Use this when the genie emits a skill.confirmation_required event.

bash
POST /api/v1/genies/:genie_handle/chat/conversations/:conversation_id/skill_approval/:call_id

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
conversation_idstring
required
Conversation ID.
call_idstring
required
Call ID from the skill.confirmation_required event.

Payload

NameTypeDescription
resolutionstring
required
One of approved or rejected.
rejection_reasonstring
optional
Reason for rejection. Only used when resolution is rejected.

Get an authentication link for a runtime connection. Use this when the genie emits a runtime_connection.auth_required event.

bash
POST /api/v1/genies/:genie_handle/chat/runtime_connection/:runtime_connection_attempt_id/link
NameTypeDescription
genie_handlestring
required
Genie handle.
runtime_connection_attempt_idstring
required
Server-generated ID for the pending runtime-connection authorization attempt, as delivered in the runtime_connection.auth_required SSE event.
NameTypeDescription
statusstringOne of auth_required or authorized. When authorized, the connection is already complete and no user action is needed.
auth_link.urlstringAuthentication URL to present to the user. Only present when status is auth_required.
auth_link.expires_atstringExpiration time of the authentication URL in RFC3339 format. Only present when status is auth_required.
auth_link.connector_namestringHuman-readable connector label (for example, Salesforce, Google Drive). Only present when status is auth_required.

Reject a runtime connection

Reject a runtime connection request.

bash
POST /api/v1/genies/:genie_handle/chat/runtime_connection/:runtime_connection_attempt_id/reject

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
runtime_connection_attempt_idstring
required
Server-generated ID for the pending runtime-connection authorization attempt, as delivered in the runtime_connection.auth_required SSE event.

Payload

NameTypeDescription
reasonstring
optional
Reason for rejection.

Upload a file

Upload a file to attach to a subsequent message. Returns a file_id to pass in the file_id parameter of Send a message.

bash
POST /api/v1/genies/:genie_handle/chat/conversations/:conversation_id/upload

URL parameters

NameTypeDescription
genie_handlestring
required
Genie handle.
conversation_idstring
required
Conversation ID.

Payload

NameTypeDescription
filefile
required
File data (multipart/form-data).

Response

NameTypeDescription
file_idstringID of the uploaded file.

SSE events

You can send a message with stream: true to get a response with a stream of SSE covering the full lifecycle of the genie's response.

Events are persisted for 24 hours and are retrievable through the Get events endpoint.

Base event shape

Every event shares the following base fields:

FieldTypeDescription
conversation_idstringConversation ID.
genie_handlestringGenie handle (string identifier, for example gin-AaDX9axF-CNtgQn-B6).
genie_run_idstringID of the genie run this event belongs to.
typestringEvent type.
event_idstringUUIDv7 identifying this event.
seq_numintegerPer-genie-run monotonic sequence number.
created_atstringGateway-side timestamp when the event was persisted, in RFC3339 format.

Event types

EventAdditional fieldsDescription
processing.startedGenie has begun processing the request.
processing.finishedGenie has completed processing.
agent.message
  • message
The genie's response message.
skill.running
  • skill_name
  • skill_id
A skill has started executing.
skill.completed
  • skill_name
  • skill_id
A skill completed successfully.
skill.failed
  • skill_name
  • skill_id
  • error
A skill execution failed.
skill.confirmation_required
  • call_id
  • skill_name
  • skill_id
  • skill_parameters
  • skill_parameter_schema
A skill requires user confirmation before executing. Use call_id with Approve or reject a skill.
runtime_connection.auth_required
  • runtime_connection_attempt_id
  • auth_link
A skill requires the user to authenticate a connection. Use runtime_connection_attempt_id with Get a runtime connection link.
runtime_connection.auth_successRuntime connection authentication succeeded.
runtime_connection.auth_failed
  • connection_type
  • connection_description
Runtime connection authentication failed.

Limitations

Headless API endpoints have the following limitations:

Last updated: