# Zapini API — External Functions

Manage external functions — webhook endpoints that allow external systems to trigger WhatsApp actions (send messages, manage contacts, control automations). Each function gets a unique API key for authentication.

**Requirement:** An active AI Agent integration on your account.

**Base URL:** `https://zapini.app/api/v1`

**Authentication:** `Authorization: Bearer {token}`

---

## Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/external-functions` | List all external functions |
| POST | `/external-functions` | Create a new external function |
| GET | `/external-functions/{uuid}` | Get external function details |
| PUT | `/external-functions/{uuid}` | Update external function |
| DELETE | `/external-functions/{uuid}` | Delete external function |
| POST | `/external-functions/{uuid}/toggle` | Toggle enabled/disabled |
| POST | `/external-functions/{uuid}/regenerate-key` | Regenerate API key |
| GET | `/external-functions/{uuid}/logs` | List execution logs |

---

## List External Functions

```
GET /api/v1/external-functions
```

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `instance_uuid` | string | Filter by WhatsApp instance UUID |
| `enabled` | boolean | Filter by enabled status |
| `search` | string | Search by name, slug, or description |
| `per_page` | integer | Results per page (max 100, default 20) |

**Example:**

```bash
curl -X GET "https://zapini.app/api/v1/external-functions?enabled=true" \
  -H "Authorization: Bearer {token}"
```

---

## Create External Function

```
POST /api/v1/external-functions
```

**Body Parameters:**

| Parameter | Required | Type | Description |
|-----------|----------|------|-------------|
| `instance_uuid` | Yes | string | UUID of the WhatsApp instance |
| `name` | Yes | string | Function name |
| `slug` | Yes | string | URL slug (lowercase, hyphens only) |
| `action_type` | Yes | string | Action type (see below) |
| `description` | No | string | Function description |
| `config` | No | object | Action-specific configuration |
| `rate_limit` | No | integer | Max calls per day (default: 1000) |
| `allowed_ips` | No | array | Allowed IP addresses (empty = all) |
| `is_enabled` | No | boolean | Whether function is active |

> **Important:** The `api_key` is returned only once in the create response. Store it securely.

**Example:**

```bash
curl -X POST "https://zapini.app/api/v1/external-functions" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "instance_uuid": "abc-123-def",
    "name": "CRM Order Notification",
    "slug": "crm-order-notify",
    "action_type": "send_message",
    "description": "Sends order status updates from CRM",
    "config": {
      "message_template": "Order {{order_id}}: {{status}}"
    },
    "rate_limit": 500,
    "allowed_ips": ["203.0.113.10"]
  }'
```

**Response includes:**

```json
{
  "success": true,
  "data": {
    "uuid": "...",
    "api_key": "efk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "api_key_warning": "Store this key securely. It will not be shown again.",
    "endpoint_url": "https://zapini.app/api/v1/external/crm-order-notify",
    ...
  }
}
```

---

## Update External Function

```
PUT /api/v1/external-functions/{uuid}
```

Same parameters as Create (except `instance_uuid` is optional for updates).

---

## Delete External Function

```
DELETE /api/v1/external-functions/{uuid}
```

Deletes the function and all its execution logs.

---

## Toggle External Function

```
POST /api/v1/external-functions/{uuid}/toggle
```

Toggles the `is_enabled` state.

---

## Regenerate API Key

```
POST /api/v1/external-functions/{uuid}/regenerate-key
```

Generates a new API key and invalidates the old one. The new key is only returned once.

**Response:**

```json
{
  "success": true,
  "data": {
    "uuid": "...",
    "api_key": "efk_new_key_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "api_key_prefix": "efk_new_",
    "api_key_warning": "Store this key securely. It will not be shown again."
  }
}
```

---

## List Logs

```
GET /api/v1/external-functions/{uuid}/logs
```

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `status` | string | Filter: success, error, unauthorized, rate_limited |
| `per_page` | integer | Results per page (max 100, default 20) |

---

## Available Action Types

| Action | Description |
|--------|-------------|
| `send_message` | Send a text message |
| `send_buttons` | Send a message with buttons |
| `send_media` | Send media (image, video, document) |
| `create_contact` | Create a new contact |
| `update_contact` | Update an existing contact |
| `create_lead` | Create a Kanban lead |
| `update_lead` | Update a Kanban lead |
| `pause_automation` | Pause AI automation for a conversation |
| `resume_automation` | Resume AI automation for a conversation |

---

## Error Codes

| Code | HTTP | Description |
|------|------|-------------|
| `AI_AGENT_NOT_ENABLED` | 403 | No active AI Agent integration |
| `DUPLICATE_SLUG` | 422 | Slug already exists for this account |
| `NOT_FOUND` | 404 | Function or instance not found |
