Texa DeskDevelopers

Webhooks

Texa API webhooks

Signed events for every conversation, reply, action, handover and call, retried for about a day.

Texa POSTs each event to your server as it happens. Add an endpoint in Texa Desk under Texa AI → Developers → Webhooks: its URL, live or sandbox events, and every event type or the ones you pick. You get a signing secret, shown once.

  • Live endpoints must be https and reachable from the internet. Sandbox endpoints may use http while you build (through a tunnel such as ngrok: private addresses are never called).
  • Send a test event in Texa Desk posts a ping at once and shows the answer.

What arrives

POST https://your-server/texa/webhooks
Content-Type: application/json
X-Texa-Timestamp: 1790000000
X-Texa-Signature: sha256=5d41402abc4b2a76b9719d911017c592...
X-Texa-Event-Id: evt_431
X-Texa-Event-Type: conversation.reply
X-Texa-Delivery-Id: whd_12

{"id": "evt_431", "type": "conversation.reply", "created_at": "2026-09-27T10:00:03Z",
 "environment": "live", "conversation_id": "cnv_8a7f0c...",
 "data": {"type": "reply", "reply_id": "rpl_...", "format": "chat", "text": "..."}}

The body is the same event as on GET /v1/events, plus environment.

Check it came from Texa

Compute the signature over the raw body, before any JSON parsing, and compare in constant time. Reject a timestamp more than 5 minutes old.

import hashlib, hmac, time

def verify(secret: str, headers, raw_body: bytes) -> bool:
    ts = headers["X-Texa-Timestamp"]
    if abs(time.time() - int(ts)) > 300:
        return False
    expected = "sha256=" + hmac.new(secret.encode(), ts.encode() + b"." + raw_body,
                                    hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, headers["X-Texa-Signature"])

The same signature scheme is used on every request Texa sends you: action webhooks and monitor alerts too.

Answer fast, handle once

  • Answer any 2xx within 10 seconds, then do the work. Anything else, or no answer, is tried again after 1 minute, 5 minutes, 30 minutes, then 2, 5, 10 and 10 hours: 8 attempts over about a day. After that the delivery is marked failed, and you can send it again from Texa Desk.
  • Delivery is at least once: use X-Texa-Event-Id (or the body's id) to ignore a repeat.
  • Order is not guaranteed across retries. Use created_at, or the feed, when order matters.
  • An endpoint whose every delivery has failed for 5 days is switched off, and Texa Desk says so. Switch it on again once it is fixed.
  • Each delivery's attempts (time, status, error) are in Texa Desk, for 30 days.

The feed, GET /v1/events?after=<cursor>, is the complete record. If your server was down, read the feed from your last cursor instead of waiting for retries.

Event types

Type When
conversation.opened a conversation was opened
conversation.reply Texa AI replied, including replies that came after your request returned
conversation.action_request Texa AI asked for an action (codes the customer typed are masked here)
conversation.handover Texa AI handed the conversation to people
conversation.handback people handed it back to Texa AI
conversation.closed it was closed; resolved says whether Texa AI resolved it
conversation.human_message a person answered from Texa Desk: show text in your app (handing over)
call.started, call.ended a phone or in-app call started or ended
media.understood, media.failed a voice note, photo, document or video was understood, or could not be
quality.scored a closed conversation was scored
monitor.finding one of your monitors found something
interview.completed a research interview was completed
report.ready a report is ready
survey.response a customer completed a survey
ping a test event you sent from Texa Desk

New types may be added. Ignore types you do not know, and subscribe to types by name if you want only those.