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:

Request body

The body must be application/json. Unknown fields are rejected.

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:
Every response that produced or continued a chat also carries the chat ID in a response header:

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.
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.

Forwarding headers to your MCP server

If your agent uses a remote MCP server — one Pinkfish proxies to at a URL you operate — you can pass per-request headers from the API channel straight through to that server. This is how you do per-end-user authentication and authorization at your own MCP server. The channel’s X-API-Key authenticates the channel, not the person on whose behalf you are calling, so if your MCP server needs to know which user this request is for, send that yourself. Any request header you send with the reserved prefix X-Pf-Forward- is forwarded to your remote MCP server with the prefix stripped:
Your MCP server receives:
There is nothing to configure — no allowlist to register, no setting in the agent builder. The prefix is the whole mechanism, and it is also the security boundary: headers without it are never forwarded.
Look the header up case-insensitively. The name reaches your server lowercased — X-Pf-Forward-User-Id arrives as user-id, not User-Id. This is valid HTTP (header names are case-insensitive) and most frameworks handle it for you, but if yours exposes a raw map — Go’s r.Header indexed directly, some Python and Node handlers — an exact-case lookup returns empty with no error and no warning. Read it case-insensitively.

What gets forwarded

content-type, accept, authorization, and mcp-session-id are dropped even if you deliberately prefix them, so a forwarded header can never override content negotiation, the session, or the credential Pinkfish sends upstream.
The authorization header your MCP server receives is the credential from the connection backing that server, not the X-API-Key you sent to the channel. Use a forwarded header for end-user identity; use the connection for the server’s own credential.

Requirements

Two conditions have to hold, and when either fails the tool simply does not appear — there is no error message pointing at the cause:
  • The server must be a remote MCP server — one registered against a URL you operate. Servers generated from an OpenAPI spec, and Pinkfish’s built-in embedded services, do not receive forwarded headers. See Custom MCP Servers.
  • A connection must resolve for that server. Remote servers fetch their credential from a connection matched on service key. With no matching connection the server’s tools never load at all.

Isolation between users

Forwarded headers are part of the key for the cached session to your MCP server, so two requests carrying different forwarded values never share a session. Sending user-id: alice and then user-id: bob produces two independent upstream sessions — bob cannot land on a connection opened for alice.
The same prefix works when invoking an agent through the Agent Management API — both entrypoints converge on the same behavior.

Output format

Set the format on the Channels tab; it is stored per channel. 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

  • 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.