> ## Documentation Index
> Fetch the complete documentation index at: https://docs.a1base.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook

> Webhook endpoint for receiving incoming WhatsApp messages from WhatsApp servers

The webhook endpoint allows you to receive incoming WhatsApp messages in real-time. When a message is received, it will be sent to your configured webhook URL with the following payload structure.
Think of it as setting up an automatic forwarding system - whenever someone messages your AI agent on WhatsApp, we'll immediately forward that message to your specified webhook URL, so your agent can process and respond to it right away.

```json theme={null}
{
  "thread_id": "chat_123456789",
  "message_id": "msg_987654321",
  "thread_type": "individual",
  "sender_number": "+61400123456",
  "sender_name": "Jane",
  "a1_account_id": "123-123-123",
  "a1_phone_number": "+1415123456",
  "timestamp": "2024-12-20T00:48:15+00:00",
  "service": "whatsapp",
  "message_type": "text",
  "is_from_agent": false,
  "message_content": {
    "text": "Hello world"
  }
}
```

> [!TIP]
>
> This webhook will receive all incoming messages, including those created using the A1Base API. To prevent infinite loops, you may want to check the sender\_number to avoid agents replying to themselves.

### Webhook Payload

**thread\_id** `string`

Unique identifier for the chat thread

**message\_id** `string`

Unique identifier for the specific message

**thread\_type** `string`

Type of chat - can be "group", "individual", or "broadcast"

**sender\_number** `string`

Phone number of the message sender with country code. e.g. "+61400123456"

**sender\_name** `string`

Name of the message sender

**a1\_account\_number** `string` *deprecated*

Your A1Base account identifier

**a1\_account\_id** `string`

Your A1Base account identifier

**a1\_phone\_number** `string`

The A1Base phone number that received the message. e.g. "+61400999888"

**timestamp** `string`

When the message was handled on WhatsApp, in ISO 8601 format. e.g. "2024-12-20T00:48:15+00:00"

**service** `string`

The messaging service used (e.g. "whatsapp")

**message\_type** `string`

Type of the message. Can be one of: "text", "rich\_text", "image", "video", "audio", "reaction", "group\_invite", "location", "unsupported\_message\_type"

**is\_from\_agent** `boolean`

Whether the message was sent by an agent

**message\_content** `object`

The complete message content object containing all message data. Structure varies by message\_type:

For message\_type: "text" (simple text)

```json theme={null}
{
  "text": "Hello world"
}
```

For message\_type: "rich\_text" (rich text with optional quote)

```json theme={null}
{
  "text": "This is a reply to something",
  "quoted_message_content": "Original message that was replied to",
  "quoted_message_sender": "61400123456"
}
```

For message\_type: "image"

```json theme={null}
{
  "data": "base64_encoded_image_data"
}
```

For message\_type: "video"

```json theme={null}
{
  "data": "base64_encoded_video_data"
}
```

For message\_type: "audio"

```json theme={null}
{
  "data": "base64_encoded_audio_data"
}
```

For message\_type: "reaction"

```json theme={null}
{
  "reaction": "👍"
}
```

For message\_type: "group\_invite"

```json theme={null}
{
  "groupName": "My WhatsApp Group",
  "inviteCode": "Ab12Cd34"
}
```

For message\_type: "location"

```json theme={null}
{
  "latitude": -33.8688,
  "longitude": 151.2093,
  "name": "Optional location name",
  "address": "Optional address"
}
```

For message\_type: "unsupported\_message\_type"

```json theme={null}
{
  "error": "Unsupported Message Type"
}
```

**x-signature** `string`

HMAC-SHA256 signature used to verify the authenticity of the webhook. Created using your API secret and the timestamp + request body.

**x-timestamp** `string`

Unix timestamp (in seconds) when the webhook was sent. Used to verify the request and prevent replay attacks.

### Response Codes

* `200`: Message received successfully
* `403`: Invalid secret key
* `500`: Internal server error

> **Setting up your webhook**
>
> 1. Create an endpoint in your application to receive webhook events:
>
> ```typescript theme={null}
> import express from 'express';
> import { WhatsAppIncomingData } from 'a1base-node';
>
> const app = express();
> app.use(express.json());
>
> app.post('/whatsapp/incoming', async (req, res) => {
>   const {
>     thread_id,
>     message_id,
>     thread_type,
>     sender_number,
>     sender_name,
>     a1_account_id,
>     a1_phone_number,
>     timestamp,
>     service,
>     message_type,
>     is_from_agent,
>     message_content,
>   } = req.body as WhatsAppIncomingData;
>   // Process the incoming message
>   console.log(`Received message from ${sender_name}: ${message_content.text}`);
>
>   // Always respond with 200 to acknowledge receipt
>   res.json({ success: true });
> });
> ```
>
> 2. Deploy your endpoint to a public URL (e.g. using ngrok for testing)
>
> 3. Update your webhook URL on the A1Base dashboard at [https://www.a1base.com/dashboard/phone-numbers](https://www.a1base.com/dashboard/phone-numbers)
>
> For a complete implementation example including message handling and AI responses, see our chat agent example:
>
> ```typescript:examples/chat-agent.mdx theme={null}
> startLine: 130
> endLine: 209
> ```

> **Security best practices**
>
> * Validate the webhook payload structure matches the expected format
> * Check the sender\_number to avoid infinite loops with your own agent
> * Use HTTPS endpoints only
> * Keep your webhook URL private
> * Implement rate limiting if needed
> * Add error handling for failed message processing
> * All webhook requests from A1Base include an `x-signature` and `x-timestamp` header.
> * You can verify the authenticity of each request using your API secret and the HMAC-SHA256 algorithm.
> * Here's how the signature is generated on our side:
>
>   ```ts theme={null}
>   const message = timestamp + JSON.stringify(body);
>   const signature = crypto
>     .createHmac('sha256', apiSecret)
>     .update(message)
>     .digest('hex');
>   ```
>
> On your server, do the following to verify the signature:
>
> 1. Read the raw JSON body of the request
> 2. Get the x-timestamp header
> 3. Recreate the message string as timestamp + rawBody
> 4. Generate your own HMAC signature with your API secret
> 5. Compare it with the x-signature using a constant-time comparison
>
> **Example in Express (Node.js)**
>
> ```ts theme={null}
> import crypto from 'crypto';
> import express from 'express';
> const app = express();
>
> app.use(express.json({
>   verify: (req, res, buf) => {
>     req.rawBody = buf; // capture raw body for HMAC check
>   }
> }));
>
> app.post('/whatsapp/incoming', (req, res) => {
>   const rawBody = req.rawBody.toString();
>   const timestamp = req.headers['x-timestamp'];
>   const receivedSig = req.headers['x-signature'];
>   const secret = process.env.A1BASE_API_SECRET;
>
>   const expectedSig = crypto
>     .createHmac('sha256', secret)
>     .update(timestamp + rawBody)
>     .digest('hex');
>
>   if (receivedSig !== expectedSig) {
>     return res.status(403).send('Invalid signature');
>   }
>
>   // Continue processing the verified request
>   res.sendStatus(200);
> });
> ```
>
> > [!TIP]
> >
> > Reject any webhook requests with a timestamp older than 5 minutes to prevent replay attacks.


## OpenAPI

````yaml POST /whatsapp/incoming
openapi: 3.1.0
info:
  title: A1Base API
  description: API for sending and receiving messages across messaging platforms
  version: 0.1.0
servers:
  - url: https://api.a1base.com/v1
    description: A1Base API server
  - url: https://your.endpoint.com
    description: Your webhook endpoint
security:
  - apiKeyAuth: []
    apiSecretAuth: []
paths:
  /whatsapp/incoming:
    post:
      summary: Receive WhatsApp Message
      description: >-
        Webhook endpoint for receiving incoming WhatsApp messages from WhatsApp
        servers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - thread_id
                - message_id
                - thread_type
                - content
                - sender_number
                - sender_name
                - a1_account_id
                - timestamp
                - service
                - message_type
                - is_from_agent
                - message_content
              properties:
                thread_id:
                  type: string
                  description: Unique identifier for the chat thread
                message_id:
                  type: string
                  description: Unique identifier for the specific message
                thread_type:
                  type: string
                  enum:
                    - group
                    - individual
                    - broadcast
                  description: Type of chat
                content:
                  type: string
                  description: The message content/text
                sender_number:
                  type: string
                  description: Phone number of the message sender
                sender_name:
                  type: string
                  description: Name of the message sender
                a1_account_id:
                  type: string
                  description: Your A1Base account identifier
                timestamp:
                  type: string
                  description: A timestamp in ISO 8601 format
                service:
                  type: string
                  enum:
                    - whatsapp
                    - telegram
                  description: The messaging service
                message_type:
                  type: string
                  enum:
                    - text
                    - image
                    - video
                    - audio
                    - document
                  description: Type of message content
                is_from_agent:
                  type: boolean
                  description: Whether the message is from an agent
                message_content:
                  type: object
                  description: Structured message content
                  properties:
                    text:
                      type: string
                      description: Text content of the message
      responses:
        '200':
          description: Message received successfully
        '500':
          description: Internal server error
      servers:
        - url: https://your.endpoint.com
          description: Your webhook endpoint
components:
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
    apiSecretAuth:
      type: apiKey
      in: header
      name: X-API-Secret

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.