Agent BrainsAgent Brains
APIWebhooks

Webhook event types

Complete request envelope, message payload, control payload and signature headers delivered to your receiver.

AgentBrains sends an HTTPS POST with a JSON body to your subscription URL. Your receiver handles two version-1 event types. Each body has the following shape. Property names ending in ? are optional. Other properties are required.

type Sender = {
  type: "customer" | "ai" | "human" | "system" | "unknown";
  external_id?: string;
};

type MessageData = {
  message_id: string;
  body: string;
  direction: "incoming" | "outgoing";
  sender: Sender;
  created_at: string;
  client_message_id?: string;
};

type ControlData = {
  previous_mode: "ai" | "human";
  mode: "ai" | "human";
  control_version: number;
};

type EventEnvelope = {
  id: string;
  version: 1;
  occurred_at: string;
  tenant_id: string;
  employee_id: string;
  conversation_id: string;
  recipient_id: string;
  channel: "web-chat" | "email";
  sequence: number;
  is_test: boolean;
};

type WebhookEvent =
  | (EventEnvelope & {
      type: "message.created";
      data: MessageData;
    })
  | (EventEnvelope & {
      type: "conversation.control_changed";
      data: ControlData;
    });

Envelope fields

FieldType and meaning
idNonempty string identifying this event. Stable across retries. Deduplicate using this field.
typeLiteral message.created or conversation.control_changed. Selects the corresponding data type.
versionInteger literal 1.
occurred_atRFC 3339 UTC timestamp string.
tenant_idWorkspace ID bound to the subscription.
employee_idEmployee expertId associated with the campaign.
conversation_idID of the conversation that produced the event.
recipient_idID of the associated recipient.
channelLiteral web-chat or email.
sequencePositive integer allocated per conversation, shared across both event types. Deliveries can arrive out of order.
is_testBoolean indicating synthetic QA activity. External subscriptions exclude events marked true.

Message payload

FieldType and meaning
message_idNonempty stored message ID. Use it to merge this event with structured history.
bodyNonempty stored text.
directionLiteral incoming or outgoing.
sender.typeLiteral customer, ai, human, system or unknown.
sender.external_idOptional nonempty string, up to 255 characters. External operator identity supplied by the integration.
created_atMessage persistence timestamp as an RFC 3339 UTC string.
client_message_idOptional nonempty string, up to 255 characters. Included for an operator command.

message.created reports persistence. Its body has no customer delivery status. Use the structured message returned by the operator endpoint or history to inspect delivery_status.

Control payload

FieldType and meaning
previous_modeLiteral ai or human before the transition.
modeLiteral ai or human after the transition.
control_versionPositive integer after the transition. Pass it as expected_version for the next change.

A request that repeats the current mode produces no new control event.

Delivery headers

HeaderType and meaning
Content-Typeapplication/json.
X-AgentBrains-Event-IdSame string as body id.
X-AgentBrains-TimestampDecimal Unix timestamp in seconds for this HTTP attempt.
X-AgentBrains-Signaturev1= followed by the hex HMAC-SHA256 of <timestamp>.<raw body>.

Verify the signature over the raw UTF-8 bytes using the literal signing-secret string. Compare in constant time and reject timestamps outside five minutes. Signatures and delivery timestamps change on retry. Event IDs and bodies remain stable.

Receiver responses

Return any HTTP 2xx after durable acceptance. Network failures, 408, 429 and 5xx are retried for up to 24 hours. A 410 response disables the subscription. Redirects and other non-retryable HTTP responses end that delivery attempt series.

See the conversation integration guide for processing order, history synchronization and the full test flow.

On this page