Application endpoints

Start a session and send chat messages to your agent, per application, over a streamed connection.

Every application's chat is built on two endpoints, scoped to that application's ID, and listed for you on the application's Application Endpoints tab. Both are POST requests and both need one of the authentication headers described below; only the chat endpoint streams its response, the session endpoint answers with a single JSON object. A third endpoint, not shown on that tab, lets you end a session early.

https://mcp-host.tuix.ch/stream/<ApplicationId>/session
https://mcp-host.tuix.ch/stream/<ApplicationId>/chat

Application Endpoints tab with the session and chat URLs

Authentication

Both endpoints require one of the following headers:

HeaderRequiredDescription
AuthorizationOne of Authorization or X-Api-KeyThe value your own API expects, typically the end user's Bearer token. Tuix AI Agents forwards it as Authorization: Bearer <value> to every MCP server connected to this application, and from there to your API, so the agent acts with this identity.
X-Api-KeyOne of Authorization or X-Api-KeyAn API key from API keys, used to authenticate the call to Tuix AI Agents when Authorization header is not provided

Whichever header authenticates the call, Authorization or X-Api-Key, Tuix AI Agents forwards the underlying credential downstream as a single Authorization: Bearer <credential> header, not as whatever header you originally sent it in:

You sendYour API receives
Authorization: Bearer abc123Authorization: Bearer abc123
X-Api-Key: abc123Authorization: Bearer abc123

There is no separate X-Api-Key forwarding at this layer, so your own API must accept the credential on its Authorization header for the chat flow to reach it. (A generated MCP server called directly, without going through Tuix AI Agents, does support a separate X-Api-Key header, see Authorization.)

An X-Api-Key must never be exposed to the browser or shipped in client code: anyone who reads it can call every application in your account. For a public-facing chat, put a backend between your frontend and Tuix AI Agents, and keep the key there.

Session endpoint

Call this once to start a conversation.

POST https://mcp-host.tuix.ch/stream/<ApplicationId>/session

Body

{
    "userId": "<identifier>"
}

userId can be a random identifier or a real user ID from your own system. It is only used as an additional identifier for your session; Tuix AI Agents does not look it up anywhere.

Response

{
    "sessionId": "session-192838110457-7be04c1e",
    "userId": "<identifier>",
    "sessionSecret": "p9QzT2mX_kLr8wYVdN3s...",
    "createdAt": "2026-09-16T09:14:02.331904512Z",
    "initialMessage": "Hello! How can I assist you today?"
}

Save sessionId and sessionSecret. Both are required for the rest of the conversation and cannot be retrieved again afterwards.

initialMessage is the application's configured Initial Message, returned here so you can show it immediately, without waiting for the agent to say anything.

Example

These examples authenticate with X-Api-Key, read alongside the base URL and application ID from the environment. Swap it for an Authorization header if you're acting on behalf of a signed-in user instead, see Authentication.

const startSession = async (userId: string) => {
    const response = await fetch(
        `${process.env.MCP_HOST_BASE_URL}/stream/${process.env.APPLICATION_ID}/session`,
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Api-Key': process.env.TUIX_AI_AGENTS_API_KEY!,
            },
            body: JSON.stringify({ userId }),
        },
    )
 
    if (!response.ok) {
        throw new Error(`Failed to start session: ${response.status}`)
    }
 
    return response.json()
    // { sessionId, userId, sessionSecret, createdAt, initialMessage }
}

Chat endpoint

Call this to send a message and receive the agent's streamed reply.

POST https://mcp-host.tuix.ch/stream/<ApplicationId>/chat

Body

{
    "sessionId": "session-192838110457-7be04c1e",
    "message": "<your message>"
}

Headers

HeaderRequiredDescription
x-session-secretYesThe sessionSecret returned by the session endpoint.
Authorization / X-Api-KeyYes, one of the twoSame as for the session endpoint, see Authentication above.

The response stream

The chat endpoint answers with a stream of typed events rather than a single JSON payload, so your interface can show progress as the agent works instead of a blank screen. Each event has a type and a data payload.

TypeWhen it happens
thinkingThe agent has started processing the message.
tool-callThe agent is calling one of its connected tools (an MCP server action).
tool-resultA tool call finished and returned data.
chunkA piece of the agent's text reply, arriving as it is generated.
completeThe full reply is ready, together with usage/context information.
errorSomething failed, e.g. a downstream API error or the model provider being busy.
doneThe stream has ended. Always the last event, whether the turn succeeded or not.

A typical turn that calls a tool, here one that creates an order, looks like this:

type: thinking
data: {"message":"Processing your request...","timestamp":"2026-09-16T09:15:40Z"}

type: tool-call
data: {"timestamp":"2026-09-16T09:15:41Z","toolCall":{"assistantMessage":{"content":"[{\"input\":{\"productId\":\"prod_2f81\",\"quantity\":2},\"toolCallId\":\"fc_5e21c9b4-7a3d-4f10-9c6e-2d8b1a4f6e5c\",\"toolName\":\"create_order\",\"type\":\"tool-call\"}]","role":"assistant"}}}

type: tool-result
data: {"timestamp":"2026-09-16T09:15:42Z","toolResult":{"content":"{\"content\":[{\"text\":\"{\\\"orderId\\\":\\\"ord_9c14a7\\\",\\\"status\\\":\\\"confirmed\\\",\\\"productId\\\":\\\"prod_2f81\\\",\\\"quantity\\\":2,\\\"total\\\":59.98}\",\"type\":\"text\"}]}","name":"create_order","role":"tool","tool_call_id":"fc_5e21c9b4-7a3d-4f10-9c6e-2d8b1a4f6e5c"}}

type: thinking
data: {"message":"Processing your request...","timestamp":"2026-09-16T09:15:42Z"}

type: chunk
data: {"chunk":"###","timestamp":"2026-09-16T09:15:42Z"}

... more chunk events, one per piece of text ...

type: complete
data: {"message":"order 2 units of prod_2f81","response":{"content":"### Order confirmed\n\n| Field | Value |\n| --- | --- |\n| Order ID | ord_9c14a7 |\n| Product | prod_2f81 |\n| Quantity | 2 |\n| Total | 59.98 |","contextPercentage":1.42,"maxTokens":100000,"tokensUsed":1420},"timestamp":"2026-09-16T09:15:42Z"}

type: done
data: {"timestamp":"2026-09-16T09:15:42Z"}

chunk events carry the reply as it is written, so you can render it progressively. complete carries the same reply in full, plus tokensUsed/maxTokens/contextPercentage, useful for showing how much of the conversation's context budget is used. Always wait for done before considering the turn finished, and treat a stream that ends without a done event as a failure, not a silent success.

Example

const sendMessage = async (sessionId: string, sessionSecret: string, message: string) => {
    const response = await fetch(
        `${process.env.MCP_HOST_BASE_URL}/stream/${process.env.APPLICATION_ID}/chat`,
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'x-session-secret': sessionSecret,
                'X-Api-Key': process.env.TUIX_AI_AGENTS_API_KEY!,
            },
            body: JSON.stringify({ sessionId, message }),
        },
    )
 
    if (!response.ok || !response.body) {
        throw new Error(`Chat request failed: ${response.status}`)
    }
 
    const reader = response.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''
 
    while (true) {
        const { done, value } = await reader.read()
        if (done) break
 
        buffer += decoder.decode(value, { stream: true })
        const lines = buffer.split('\n')
        buffer = lines.pop() ?? ''
 
        for (const line of lines) {
            if (line) console.log(line) // "type: ..." or "data: {...}"
        }
    }
}

End a session early

Sessions also end on their own after 1 hour, but you can delete one sooner:

DELETE https://mcp-host.tuix.ch/stream/<ApplicationId>/session/<sessionId>

Requires the same Authorization/X-Api-Key header as the other two endpoints, no body. A successful delete answers 204 No Content. See Request reference for the full status codes.

Session duration

A session lasts 1 hour. After that, its chat history and the session itself expire, and sending a message with an expired sessionId fails. Call the session endpoint again to start a new one; the previous conversation's context is not carried over.

On this page