# Custom Webhook

> Use Aerostack bots with any platform via the custom webhook endpoint — send JSON, get AI responses.

The custom webhook lets you connect an Aerostack bot to **any platform, application, or service** that can make HTTP requests. There is no platform-specific adapter — you send a JSON payload and receive a structured JSON response.

---

## Webhook URL

```
POST https://api.aerostack.dev/api/bots/webhook/custom/:botId
```

---

## Request Format

Send a POST request with a JSON body:

```bash
curl -X POST https://api.aerostack.dev/api/bots/webhook/custom/bt_YOUR_BOT_ID \
  -H "Content-Type: application/json" \
  -d '{
    "text": "What is the status of order #12345?",
    "user_id": "user_abc123",
    "channel_id": "channel_main",
    "user_name": "Jane Doe"
  }'
```

### Request Body Fields

| Field | Required | Description |
|-------|----------|-------------|
| `text` | Yes | The message text to process |
| `user_id` | Yes | A unique identifier for the user. Used for conversation tracking. |
| `channel_id` | Yes | A channel/context identifier. Different channels maintain separate conversations. |
| `user_name` | No | Display name for the user (passed to the LLM as context) |

---

## Response Format

The custom webhook returns a structured JSON response (unlike other platforms that send responses asynchronously):

```json
{
  "response": "Order #12345 is currently being shipped. It was dispatched on March 14th and the estimated delivery is March 17th.",
  "tool_calls": [
    {
      "toolName": "orders__get_order",
      "arguments": { "order_id": "12345" },
      "result": { "status": "shipped", "dispatched_at": "2026-03-14" },
      "latencyMs": 230,
      "success": true
    }
  ],
  "tokens": { "input": 485, "output": 42 },
  "cost_cents": 1,
  "latency_ms": 2340
}
```

### Response Fields

| Field | Type | Description |
|-------|------|-------------|
| `response` | string | The bot's text response |
| `tool_calls` | array | List of MCP tools called during processing, with arguments and results |
| `tokens` | object | Token usage breakdown (`input` and `output`) |
| `cost_cents` | number | Cost in cents (0 for BYOK mode) |
| `latency_ms` | number | Total processing time in milliseconds |

---

## Conversation Tracking

The custom webhook uses `user_id` + `channel_id` to track conversations, just like other platforms:

- Messages from the same `user_id` in the same `channel_id` are part of the same conversation
- Conversations expire after `conversation_ttl_hours` (default 24 hours)
- After expiry, a new conversation starts automatically

Use different `channel_id` values to maintain separate conversation threads for the same user.

---

## No Built-In Verification

The custom webhook has **no built-in signature verification**. Anyone who knows your bot ID and the webhook URL can send messages. Implement your own authentication layer if this endpoint is exposed publicly.

### Recommended Security Measures

If you expose the custom webhook publicly, consider:

1. **Proxy through your own server** — validate requests before forwarding to Aerostack
2. **Use obscure bot IDs** — bot IDs include a UUID component, making them hard to guess
3. **Set a spending cap** — limit the bot's total spend to contain abuse
4. **Monitor analytics** — watch for unusual patterns via the analytics endpoint

---

## Use Cases

The custom webhook is ideal for:

- **Internal tools** — Embed AI chat in admin dashboards or internal portals
- **Custom chat UIs** — Build your own chat interface with Aerostack as the backend
- **IoT devices** — Connect voice assistants or smart displays
- **Other messaging platforms** — Any platform not natively supported (e.g., Matrix, IRC, LINE)
- **Testing and development** — Quick integration testing without setting up a full platform

---

## Example: Simple Chat Client

```typescript
// Simple Node.js chat client
async function chat(botId: string, message: string, userId: string) {
  const response = await fetch(
    `https://api.aerostack.dev/api/bots/webhook/custom/${botId}`,
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        text: message,
        user_id: userId,
        channel_id: 'default',
      }),
    }
  );

  const data = await response.json();
  return data.response;
}

// Usage
const reply = await chat('bt_abc123', 'Hello!', 'user_1');
console.log(reply);
```

---

## Example: Python Integration

```python

def chat(bot_id: str, message: str, user_id: str) -> str:
    response = requests.post(
        f"https://api.aerostack.dev/api/bots/webhook/custom/{bot_id}",
        json={
            "text": message,
            "user_id": user_id,
            "channel_id": "default",
        },
    )
    return response.json()["response"]

reply = chat("bt_abc123", "What can you help with?", "user_1")
print(reply)
```

---

## Rate Limits

Custom webhooks are rate-limited at **60 requests per minute** per bot, the same as Telegram and WhatsApp.

---

## Platform Config

The custom platform requires no platform-specific configuration. You can leave `platform_config` as `{}` or omit it entirely.

When activating a custom bot, the response includes a warning reminding you that no built-in verification exists:

```json
{
  "status": "active",
  "webhook_url": "https://api.aerostack.dev/api/bots/webhook/custom/bt_abc123",
  "warnings": [
    "Custom platform has no built-in webhook verification. Implement HMAC signature checking in your sender."
  ]
}
```
