Get started
Authentication
Every key and token Texa uses, where you get it, where it may live, and what it reaches.
Texa has a few kinds of credential because they live in different places: your server, a web page, an app, a webhook. Use the one meant for where your code runs.
At a glance
| Credential | Looks like | Where you get it | Where it may live | Reaches |
|---|---|---|---|---|
| Texa API key, sandbox | texa_test_… |
Texa AI → Developers → API keys | your server only | your sandbox |
| Texa API key, live | texa_live_… |
the same | your server only | your live account |
| Site key | pk_live_…, pk_test_… |
Texa AI → Developers → Website and app | a web page or app | visitor chats, only from your listed websites |
| Widget session token | wst_… |
your server, POST /v1/widget-sessions |
the page or app, for one customer | that customer's conversations, for up to a few hours |
| Voice session token | one-time | your server, POST /v1/conversations/{id}/voice-sessions |
the app, once | one voice session |
| Texa Desk access token | a long random string | Texa Desk → Profile settings → Access token | your server | the Texa Desk API, as that person |
| Agent bot token | a long random string | when you create an agent bot | your bot's server | the conversations of the bot's inboxes |
| Live chat HMAC key | per website inbox | the inbox → Configuration → Identity validation | your server | signs identifier_hash for live chat |
| Webhook signing secret | per endpoint | when you add the endpoint | your server | checks that a request came from Texa |
| Platform app token | a long random string | a dedicated instance's super admin | your server | the Platform API, dedicated instances only |
Texa API keys
Send the key as a bearer token on every request:
Authorization: Bearer texa_live_...
- A key is shown once, when you make it. Texa keeps only a hash of it.
- Revoke a key in Texa AI → Developers → API keys. It stops working at once.
- Make one key per system (your backend, your WhatsApp bridge, a test laptop): the request log shows which key did what, and revoking one leaves the others working.
- A key never belongs in an app or a web page. For those, your server makes a widget session or a voice session.
Site keys and widget sessions
A site key is safe to put in a web page: it only opens visitor chats, only from the websites you list under Websites your widget runs on (the sandbox site key works anywhere), and at most 20 an hour per address. A visitor is never treated as verified.
For a signed-in customer, your server calls POST /v1/widget-sessions with its own key and the
customer's reference, and hands the page the token. The token reaches only that customer's
conversations, and expires (ttl_s, one hour by default).
Texa Desk access tokens
Every person in Texa Desk has an access token under Profile settings → Access token. Send it in
the api_access_token header:
curl https://desk.texadesk.com/api/v1/accounts/1/conversations \
-H "api_access_token: $TEXA_DESK_TOKEN"
The token acts as that person, with their role's permissions and only the inboxes and teams they see. For an integration, add a dedicated person (an administrator or a custom role with only what the integration needs) rather than using someone's own token, and reset it from their profile if it leaks.
Agent bots have their own token, sent the same way, which works only on the conversations of the inboxes the bot is connected to. Agent bots
The Client API
The Client API builds a customer-facing chat on an API inbox. It needs no secret: an inbox identifier (from the inbox's settings) and a contact identifier (returned when you create the contact). Treat the contact identifier as that customer's own secret: whoever has it can read their conversations. Turn on identity validation on the inbox so only your server can create contacts for known users.
Checking what Texa sends you
Everything Texa sends your server is signed with HMAC-SHA256: Texa API webhooks, action requests to your server, Texa Desk webhooks. Check the signature over the raw body and reject old timestamps.
import hashlib, hmac, time
def from_texa(secret: str, timestamp: str, raw_body: bytes, signature: str) -> bool:
if abs(time.time() - int(timestamp)) > 300:
return False
expected = "sha256=" + hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body,
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
import crypto from "node:crypto";
export function fromTexa(secret, timestamp, rawBody, signature) {
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = "sha256=" + crypto.createHmac("sha256", secret)
.update(`${timestamp}.`).update(rawBody).digest("hex");
return signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
function from_texa(string $secret, string $timestamp, string $rawBody, string $signature): bool {
if (abs(time() - (int) $timestamp) > 300) return false;
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
return hash_equals($expected, $signature);
}
| Sent by | Timestamp header | Signature header |
|---|---|---|
| Texa API webhooks and action requests | X-Texa-Timestamp |
X-Texa-Signature |
| Texa Desk webhooks | X-Chatwoot-Timestamp |
X-Chatwoot-Signature |
Texa Desk's webhook headers keep the names of the open-source helpdesk it is built on, so existing integrations keep working. Every SDK has a webhook check built in.