Skip to main content

Conversational interface via a REST API

Build chat widgets and apps on a thunk workflow using the conversational REST API

Conversational interface via a REST API

Use the conversational REST API when you want to build a chat-style experience (a widget, mobile app, partner portal, or internal tool) on top of an existing thunk workflow. The integration uses the same workflow work item and conversation thread the agent already understands — without email.

This is different from Inbound requests via a REST API, which starts structured workflow work items. The conversational API is for turn-by-turn chat on a workflow that has a conversation input.

Precondition. The thunk workflow must have exactly one conversation-type input property. Without that, the chat UI and conversational REST API are not available for the thunk.

What you can do

Typical integrator flow:

  1. Confirm the workflow has exactly one conversation input property

  2. Create a thunk API key (same keys as the workflow REST API)

  3. Open the OpenAPI docs for this thunk’s conversational endpoints

  4. Start a conversation (first user message) and keep the returned conversation id

  5. Send follow-up messages; poll messages or subscribe to the event stream

  6. End the workflow when the conversation is finished (POST /{convoId}/end, or End conversation in the hosted Chat UI)

Optional: attach files on a turn, upload files for structured file inputs before start, and (when enabled on the conversation property) register structured-data schemas the assistant may return with messages.

1: Confirm the conversation input

In the thunk designer, open the workflow structure and check that there is exactly one input property whose type is Conversation. That property is the chat channel for each workflow work item.

If you need a quick product check: go to Run → Inbound Requests → Chat UI. When the conversation input is present, the Chat UI button is enabled and opens the hosted chat app for the thunk. When it is missing, the Chat UI button stays disabled and an info banner explains that the chat UI is enabled only if the workflow has a conversation input property.

Steps that should not reply to the end user

Chat workflows often include steps that do internal work — looking up an order, calling a business system, or updating structured fields — without talking to the person in the chat.

For those steps, open the step’s AI Instructions and remove the end-user conversation property (typically EndUserConvo) from Output properties. When that conversation is not listed under Output properties, the AI agent will not message the end user on that step. Later steps can still reply if they list the conversation in their Output properties.

Keep the conversation property in Output properties on steps that should greet the user, ask a question, share a status update, or otherwise reply in the chat. You may still list the conversation under Input properties if the step needs to read the thread without sending a message.

This is separate from Email conversation settings such as AI messaging, Disable replies, or Message writing instructions on a Conversation property.

2: Create an API key

API keys are shared with the structured workflow REST API. They are not created on the Chat UI tab.

  1. Go to Run → Inbound Requests → API Channel

  2. Open API Keys

  3. Create a key and copy it immediately — it is shown only once

For screenshots and revoke steps, see Inbound requests via a REST API (Generate an API Key).

Keys use the thk_… prefix. Send them to the public gateway as:

X-API-Key: {api-key}

Base URL for customer integrations:

https://postern.thunk.ai/api/thunk/{thunk_id}/convo

3: Open the OpenAPI documentation

Each thunk exposes its own conversational OpenAPI document because optional data fields on start match that thunk’s workflow inputs.

  1. Go to Run → Inbound Requests → Chat UI

  2. Click View OpenAPI Documentation

That opens Swagger UI for this thunk’s conversational endpoints (paths such as /start, /{convoId}/sendMessage, /{convoId}/messages, /{convoId}/end, and /{convoId}/events).

Authorize in Swagger is not your thunk API key. The OpenAPI Authorize control expects a Bearer JWT (a product session token). Use that only for interactive try-it-out. For real integrations through postern.thunk.ai, send X-API-Key: thk_… on the request — do not paste the thunk API key into the Bearer Authorize dialog. (This differs from the workflow REST OpenAPI docs, where Authorize accepts the API key.)

4: Start a conversation

POST /start creates the workflow conversation and sends the first user message. The response includes a convoId used for every later call.

Minimal shape:

{
  "conversation": {
    "type": "message",
    "message": "Hello — I need help with my request."
  }
}

You may also send:

  • data — other workflow input fields (not the conversation property)

  • name — label for the new conversation (optional; server assigns a default if omitted)

  • displayName — label for the human on this turn (optional)

  • conversation.attachments — optional file attachments on the first message (see below)

Example with curl:

curl -X POST \
  'https://postern.thunk.ai/api/thunk/{thunk_id}/convo/start' \
  -H 'accept: application/json' \
  -H 'X-API-Key: {api-key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "conversation": {
      "type": "message",
      "message": "Hello — I need help with my request."
    }
  }'

A successful response looks like:

{
  "convoId": "{conversation-id}"
}

5: Send messages and read replies

Send a follow-up

POST /{convoId}/sendMessage stores the user turn and returns a messageId:

curl -X POST \
  'https://postern.thunk.ai/api/thunk/{thunk_id}/convo/{convoId}/sendMessage' \
  -H 'accept: application/json' \
  -H 'X-API-Key: {api-key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "message": "Here are more details."
  }'

Optional fields: displayName, attachments.

List messages

GET /{convoId}/messages returns a page of messages in chronological order (oldest first within the page). The first call (no pageToken) returns the most recent page; use pageToken / nextPageToken for older history.

Useful query parameters:

  • limit — page size

  • pageToken — pass the previous response’s nextPageToken to continue

  • since — only messages after this ISO timestamp (exclusive); use the same since on every call that includes pageToken

curl -X GET \
  'https://postern.thunk.ai/api/thunk/{thunk_id}/convo/{convoId}/messages' \
  -H 'accept: application/json' \
  -H 'X-API-Key: {api-key}'

You can also fetch one message with GET /{convoId}/message/{messageId}, or check conversation state with GET /{convoId}/info (agentWorking and ended).

Live updates (SSE)

GET /{convoId}/events is a long-lived Server-Sent Events stream. After a newMessage event, call GET /messages (optionally with since) to load the text. The stream may also emit agentStatus and periodic heartbeat keepalives (safe to ignore).

6. End the workflow

When the chat is finished — the end user is done, or your app no longer needs automation — call POST /{convoId}/end. This stops the agent, skips any active and remaining workflow steps (recording an optional reason), and marks the work item complete.

Optional body:

{
  "reason": "Customer ended the chat"
}

If you omit reason, the server uses "Conversation ended".

Example:

curl -X POST \
  'https://postern.thunk.ai/api/thunk/{thunk_id}/convo/{convoId}/end' \
  -H 'accept: application/json' \
  -H 'X-API-Key: {api-key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "reason": "Customer ended the chat"
  }'

A successful response looks like:

{
  "convoId": "{conversation-id}",
  "ended": true
}

If the workflow was already ended, the server returns 409 with { "message": "Conversation already ended" }.

Poll GET /{convoId}/info to read ended (and agentWorking) without listing messages.

On the hosted Chat UI (Run → Inbound Requests → Chat UI), end users can click End conversation above the message box for the same effect.

Attachments and file inputs

Message attachments. On POST /start (conversation.attachments) or POST /…/sendMessage (attachments), each item is { "name", "data" } where data is a base64 data: URL (the same string browsers produce from FileReader.readAsDataURL). Limits: up to 5 files and 10 MiB total decoded payload per message. When you list messages, attachments include a short-lived contentPointer download URL.

Structured file inputs on start. If the workflow’s non-conversation inputs include file fields, upload first with POST /uploadFiles, then put the returned url values into data on POST /start (do not embed large base64 blobs in the start body for those fields).

Structured data (optional)

If the conversation input property has structured data enabled, you can register JSON schemas (on POST /start or via /{convoId}/structuredDataSchemas) describing payloads the assistant may attach to messages. Listed assistant messages may then include a structuredData array. Use GET /info at the API root to see whether structuredDataEnabled is true for the thunk. Details and schemas are in the thunk’s OpenAPI document.

Choosing conversational vs workflow REST

Goal

Use

Chat turns on a workflow conversation

This article (conversational REST API)

Create / poll structured workflow work items

Did this answer your question?