Skip to content

Getting Started

Wetel is an AI agent platform for building state-driven, non-linear chat and voice agents. You create an agent, give it a persona (a system prompt describing who it is and how it should behave) and a workflow (a visual graph of nodes that decides what the agent does at each step — ask a question, call a tool, branch on the answer, respond), and then integrate that agent into your own product over GraphQL. The agent runs entirely on Wetel’s infrastructure; your app just sends messages and listens for responses.

Everything in Wetel — building an agent and running a session with one — happens through a single GraphQL API.

1. Dashboard / JWT — for building agents. When you log into Wetel (or authenticate a script with login), you get a JWT. This unlocks the full builder surface: creating and updating agents, designing workflows, managing knowledge bases, connectors, and generating API keys. This is a human/admin credential — it’s not meant to live in a running server long-term. See Authentication for the full picture.

2. API key / SDK — for runtime integration. Once an agent exists, your backend uses a long-lived API key to start sessions and your frontend uses a short-lived per-session token to send messages. This is the credential pair your product actually ships with. It cannot create or edit agents — only run them.

This page only needs the second path. For everything about creating agents and workflows, see Core API Flow and Agents.

Every single request to Wetel — regardless of which credential you’re using — must include:

x-huat-platform: customer

It is checked right after your credential. If you forget it while sending a valid credential, you’ll get an error that looks like an auth failure but isn’t:

{ "message": "Platform is not specified!" }

If you ever see this error, check the header first — not your token.

Wetel does not accept compressed request bodies. A request to any Wetel API (GraphQL, REST, the speech and avatar service, and webhook receivers) that carries a Content-Encoding header other than identity, such as gzip, deflate or br, is refused with HTTP 415. When the application answers, the body is:

{ "statusCode": 415, "code": "UNSUPPORTED_CONTENT_ENCODING", "message": "Compressed request bodies are not accepted. Send the body without Content-Encoding." }

Our public edge applies the same rule first, so a plain 415 page without that JSON is possible too: branch on the status. This is a transport refusal, not a GraphQL error: there is no errors[0].extensions.code. Browsers, fetch, axios and the usual GraphQL clients send plain JSON by default, so most integrations never see it. It appears when something in your path compresses requests: a proxy or gateway, an HTTP client with request compression switched on, or a script that pipes gzip output into curl.

Terminal window
# refused: 415
curl -sS -X POST https://api.wetel.dev/graphql \
-H 'content-type: application/json' -H 'content-encoding: gzip' \
-H 'x-huat-platform: customer' --data-binary @query.json.gz
# accepted: the same request without Content-Encoding
curl -sS -X POST https://api.wetel.dev/graphql \
-H 'content-type: application/json' -H 'x-huat-platform: customer' \
--data-binary @query.json

The fix is to remove the header and send the body uncompressed: switch off request compression in your HTTP client, gateway or proxy for calls to Wetel (a request-compression interceptor or transformRequest that gzips, a gateway’s “compress upstream requests” option), or exempt Wetel’s hostnames. A request body is at most a few megabytes, so nothing is lost. Content-Encoding: identity is accepted. Compression of responses is unchanged: keep sending Accept-Encoding as you do today.

You’ll need an API key. Getting one requires a JWT (dashboard access) — see Authentication for the full login → generateApiKey flow. For this walkthrough, assume you already have one:

<YOUR_API_KEY>

Your backend calls sdkStart with your API key, targeting an existing agent:

mutation StartSession {
sdkStart(input: { agentId: 1, clientId: "user_12345" }) {
sessionId
avatarToken
graphqlEndpoint
}
}

Headers:

x-api-key: <YOUR_API_KEY>
x-huat-platform: customer

Response:

{
"data": {
"sdkStart": {
"sessionId": 42,
"avatarToken": "<SHORT_LIVED_SESSION_TOKEN>",
"graphqlEndpoint": "https://api.wetel.dev/graphql"
}
}
}

sessionId and avatarToken are what your frontend uses from here on — never the API key.

Your frontend calls sdkSendMessage using the avatarToken:

mutation SendMessage {
sdkSendMessage(
input: { sessionId: 42, text: "Hi, what can you help me with?" }
)
}

Headers:

Authorization: Bearer <SHORT_LIVED_SESSION_TOKEN>
x-huat-platform: customer

Response:

{ "data": { "sdkSendMessage": true } }

That true is just an acknowledgment. The agent’s actual reply arrives separately — Wetel’s replies are async by design, since generating one can take a few seconds. A browser receives it over a GraphQL subscription (see Core API Flow); a server can also poll the session’s messages, as the Quickstart shows in five languages.

  • Authentication — the full credential model: JWT, API key, and session tokens, plus revocation.
  • Core API Flow — the complete sdkStart → sdkSendMessage → subscription → sdkEndSession lifecycle.
  • Agents — creating and configuring agents and workflows.
  • Multi-Tenancy — how your data stays isolated from other Wetel accounts.
  • Troubleshooting — common errors and what actually causes them.