Skip to main content
The API channel is the simplest way to call an agent from your own code. You POST a message to the agent’s channel URL with an API key, and the agent’s reply comes back in the HTTP response. No token exchange, no JSON-RPC, no MCP client. It is one of the channels on an agent’s Channels tab, alongside Slack, Microsoft Teams, Email, and A2A. Use it when you want a webhook-style “send text in, get text out” integration.
The API channel and the Agent Management API both let you invoke an agent over HTTP, but they are different surfaces. The API channel is a single per-agent URL with a dedicated key — ideal for embedding one agent in an external system. The Agent Management API is a full MCP server for managing agents (create, update, list, invoke) with your account API key. If you only need to send messages to one agent, use the API channel.

Enable the channel

  1. Open the agent and go to the Channels tab.
  2. Toggle API on.
  3. Two values appear:
    • Endpoint URL — the per-agent URL you POST to, e.g. https://triggers.app.pinkfish.ai/ext/triggers/{triggerId}.
    • API key — passed in the X-API-Key header. Use Rotate key to mint a new one; the old key stops working immediately.
  4. Optionally set the Output format (Text, Markdown, or JSON — see below).
Copy the Endpoint URL directly from the Channels tab rather than constructing it by hand — the host is environment-specific and the path segment after /ext/triggers/ is the agent’s channel trigger ID, not the agent ID.

Send a message

POST the endpoint URL with your API key and a JSON body:
curl -s -X POST "https://triggers.app.pinkfish.ai/ext/triggers/{triggerId}" \
  -H "X-API-Key: YOUR_CHANNEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Summarize today'\''s support tickets"
  }'

Request body

The body must be application/json. Unknown fields are rejected.
FieldTypeRequiredDescription
messagestringYesThe user message to send to the agent.
chatIdstringNoThe chat to continue. Omit on the first call; pass it on every follow-up to keep context. See Maintaining conversation context.
metadataobjectNoArbitrary caller-supplied key/values, forwarded to the agent as sourceMetadata.

Response

The agent runs synchronously and the reply comes back in the response body. The shape depends on the configured Output format:
  • Text (default) — Content-Type: text/plain, body is the agent’s reply text.
  • MarkdownContent-Type: text/markdown, body is the agent’s reply as Markdown.
  • JSONContent-Type: application/json. If the agent has a structured output schema, the body is that structured output verbatim. Otherwise the body is a default envelope:
{
  "chatId": "auto_xyz789",
  "output": "Here is the summary of today's support tickets..."
}
Every response that produced or continued a chat also carries the chat ID in a response header:
X-Pf-Chat-Id: auto_xyz789

Maintaining conversation context

This is the most common point of confusion. Each call that does not include a chatId starts a brand-new conversation with no memory of previous calls. If you see “the chat ID changes on every call” and the agent never remembers earlier messages, it is because you are not passing the previous chatId back.
The API channel is stateful, but you hold the conversation handle. To keep context across turns:
1

First call — omit chatId

Send just { "message": "..." }. The agent creates a fresh chat and returns its ID in the X-Pf-Chat-Id response header (and in the chatId field of the JSON envelope, if you use JSON output).
2

Capture the chat ID

Read X-Pf-Chat-Id from the response headers (or chatId from the JSON body) and store it for this conversation.
3

Follow-up calls — send the same chatId

Include "chatId": "auto_xyz789" in the body of every subsequent request. The agent reuses that chat, so it sees the full prior history.
# Turn 1 — no chatId. Capture the returned chat ID from the X-Pf-Chat-Id header.
CHAT_ID=$(curl -s -D - -o /dev/null -X POST "$ENDPOINT_URL" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"message":"My name is Vinod."}' \
  | grep -i '^X-Pf-Chat-Id:' | awk '{print $2}' | tr -d '\r')

# Turn 2 — pass the same chatId back. The agent remembers turn 1.
curl -s -X POST "$ENDPOINT_URL" \
  -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d "{\"message\":\"What is my name?\",\"chatId\":\"$CHAT_ID\"}"
A given chatId belongs to the channel that created it. If you pass a chatId that this agent’s API channel does not own, the call is rejected with 403 and reason unowned_chat_id — and your chatId is deliberately not echoed back. Always reuse a chatId that came from a previous response of this same channel.

Output format

Set the format on the Channels tab; it is stored per channel.
FormatContent-TypeBody
texttext/plainRaw assistant text (default).
markdowntext/markdownRaw assistant text as Markdown.
jsonapplication/jsonThe agent’s structured output (if it has an output schema), otherwise { "chatId", "output" }.
Choose JSON when your caller wants the chatId in the body instead of reading it from a header, or when the agent produces structured output.

Rotating the key

Use Rotate key on the Channels tab to mint a fresh X-API-Key. Rotation is atomic: the new key takes effect immediately and the previous key stops working, so update your callers before (or right after) rotating.

Errors

HTTP statusMeaning
401 / 403Missing or invalid X-API-Key, the channel was disabled, or a chatId you don’t own (unowned_chat_id).
415Body was not application/json (or used multipart/file upload, which the API channel does not accept).
400Malformed body or unknown fields.
200Success — the agent’s reply is in the body.
  • A2A protocol — expose the agent to external agent-to-agent clients.
  • Agent Management API — create, update, list, and invoke agents with your account API key.
  • Channels tab — enabling channels from the agent builder UI.