Texa DeskDevelopers

Actions in your systems

Run actions on your server

Texa sends each action request to your server, signed, over a webhook or a socket your server opens. Your credentials never leave you.

When you'd rather keep your credentials and logic on your side, Texa sends each action request to your server and you answer with the result. There are two ways to receive them.

Signed webhook Socket
Texa connects to your https URL nothing: your server connects to Texa
Needs an inbound port yes no
Good for a public API server a server behind a firewall, a laptop while you build

Both are set up in Texa Desk under Texa AI → Actions → Connectors → Your own system.

Signed webhook

Texa POSTs each request, signed with the connector's secret:

HTTP
POST https://your-server/texa/actions
X-Texa-Timestamp: 1790000000
X-Texa-Signature: sha256=<hex HMAC-SHA256 of "1790000000.<raw body>">
X-Texa-Request-Id: act_3f9c...

{"request_id": "act_3f9c...", "action": "get_transfer_status",
 "inputs": {"reference": "TX-9B2LC"}, "idempotency_key": "idem_act_3f9c...",
 "expires_at": "2026-10-19T10:05:00Z", "conversation_id": "cnv_...", "environment": "live",
 "customer": {"ref": "cw:12:345", "name": "Ngozi Eze", "phone": "+2348031234567", "email": null},
 "reply_url": "https://hooks.texadesk.com/actions/results/..."}

Check the signature, then either:

  • answer 200 with {"status": "succeeded", "data": {...}}, {"status": "not_found"} or {"status": "failed", "error": "..."} within the action's timeout, or
  • answer 202, and later POST the same body to reply_url, signed the same way.

customer says who is asking as Texa Desk knows them (the phone a WhatsApp message came from), not that they proved it. Texa AI checks identity first for actions marked for verified customers only. A request from your website or app chat also says "signed_in": true when your server signed the customer in.

Socket

Your server opens one WebSocket to Texa and keeps it open; requests come down it.

Text
wss://hooks.texadesk.com/actions/connect
Authorization: Bearer <the connector's socket key, shown once>
Direction Message
Texa → you {"type": "ready"} once connected
Texa → you {"type": "action_request", "reply_token", "request_id", "action", "inputs", "idempotency_key", "expires_at", "conversation_id"}
you → Texa {"type": "action_result", "reply_token", "status", "data", "error"}
you → Texa {"type": "ping"}, answered {"type": "pong"}
Python
# pip install websockets
import asyncio, json, os, websockets

async def main():
    async with websockets.connect("wss://hooks.texadesk.com/actions/connect",
            additional_headers={"Authorization": f"Bearer {os.environ['TEXA_SOCKET_KEY']}"}) as ws:
        async for raw in ws:
            msg = json.loads(raw)
            if msg["type"] != "action_request":
                continue
            data = await run(msg["action"], msg["inputs"], msg["idempotency_key"])
            await ws.send(json.dumps({"type": "action_result", "reply_token": msg["reply_token"],
                                      "status": "succeeded", "data": data}))

asyncio.run(main())

Reconnect when the socket drops (with a pause that grows). A request with no socket connected, or no answer before expires_at, fails, and Texa AI tells the customer honestly that it couldn't check.

Or run it from the API's answer

If your own server is already the one calling the Texa API, you don't need either: action requests come back in the answer's events, and you answer with POST /v1/conversations/{id}/action-results. See actions.