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

# GET /v1/templates

> Lists your tenant's approved WhatsApp templates with their expected variables, paginated.

Returns the WhatsApp templates for your tenant. By default only `APPROVED` ones, but you can filter by status. Each item includes the expected variables extracted from the template body, so you can build the right `variables` payload for `POST /v1/messages` with `{"type": "template"}` without keeping that list on your side.

## Endpoint

```
GET https://api.keebai.com/v1/templates
```

## Required scope

`templates:read`

## Headers

| Header          | Required | Value                    |
| --------------- | -------- | ------------------------ |
| `Authorization` | Yes      | `Bearer kbai_pk_<token>` |

## Query params

| Param        | Type     | Default    | Description                                                                                                  |
| ------------ | -------- | ---------- | ------------------------------------------------------------------------------------------------------------ |
| `page`       | `number` | `0`        | Page number, 0-indexed.                                                                                      |
| `limit`      | `number` | `50`       | Items per page, up to `100`.                                                                                 |
| `status`     | `string` | `APPROVED` | `PENDING`, `IN_REVIEW`, `APPROVED`, `REJECTED`, `PAUSED`, `DISABLED`, `IN_APPEAL`.                           |
| `channel_id` | `string` | —          | `ObjectId` to filter by a specific channel. If omitted, returns templates across all channels in the tenant. |

## Example request

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.keebai.com/v1/templates?limit=20" \
    -H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  ```

  ```js JavaScript theme={null}
  const params = new URLSearchParams({ limit: "20" });
  const resp = await fetch(`https://api.keebai.com/v1/templates?${params}`, {
    headers: { Authorization: `Bearer ${process.env.KEEBAI_API_TOKEN}` },
  });
  const { items } = await resp.json();
  ```

  ```python Python theme={null}
  import os, requests

  resp = requests.get(
      "https://api.keebai.com/v1/templates",
      params={"limit": 20},
      headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
      timeout=10,
  )
  resp.raise_for_status()
  items = resp.json()["items"]
  ```
</CodeGroup>

## Response

### 200 OK

```json theme={null}
{
  "items": [
    {
      "id": "65f3a1b2c3d4e5f6a7b8c9d0",
      "name": "welcome_v2",
      "language": "es",
      "status": "APPROVED",
      "category": "MARKETING",
      "parameter_format": "NAMED",
      "variables": ["nombre", "monto"]
    },
    {
      "id": "65f3a1b2c3d4e5f6a7b8c9d1",
      "name": "appointment_reminder",
      "language": "es",
      "status": "APPROVED",
      "category": "UTILITY",
      "parameter_format": "NAMED",
      "variables": ["nombre", "fecha", "hora"]
    }
  ],
  "page": 0,
  "limit": 20,
  "total": 2
}
```

| Field                      | Type       | Description                                                                                                                              |
| -------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `items[].id`               | `string`   | Internal `ObjectId` of the template.                                                                                                     |
| `items[].name`             | `string`   | Template name exactly as registered in Meta. This is what you pass as `template_name` when sending.                                      |
| `items[].language`         | `string`   | Language code.                                                                                                                           |
| `items[].status`           | `string`   | Template status in Meta.                                                                                                                 |
| `items[].category`         | `string`   | `MARKETING`, `UTILITY`, `AUTHENTICATION`.                                                                                                |
| `items[].parameter_format` | `string`   | `NAMED` or `POSITIONAL`. We recommend new integrations stick to `NAMED`.                                                                 |
| `items[].variables`        | `string[]` | Named variables detected in the template body. The keys of the `variables` object you send in a `template` message must match this list. |
| `page`                     | `number`   | Returned page.                                                                                                                           |
| `limit`                    | `number`   | Items per page.                                                                                                                          |
| `total`                    | `number`   | Total templates matching the filter.                                                                                                     |

### 401 / 403 / 429

Standard auth, scope, and rate limit errors.

## How to use it in your integration

```python theme={null}
import os, requests

def fetch_template_meta(template_name: str) -> dict | None:
    resp = requests.get(
        "https://api.keebai.com/v1/templates",
        params={"limit": 100},
        headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
        timeout=10,
    )
    resp.raise_for_status()
    for t in resp.json()["items"]:
        if t["name"] == template_name:
            return t
    return None

template = fetch_template_meta("welcome_v2")
if template is None:
    raise SystemExit("Template not approved yet")

required_vars = set(template["variables"])
provided = {"nombre": "Juan", "monto": "1500"}
if not required_vars.issubset(provided):
    raise ValueError(f"Missing variables: {required_vars - set(provided)}")
```

<Tip>
  Cache the `GET /v1/templates` response for a few minutes in your integration. New templates don't appear in production overnight: you create them in the portal and wait for Meta's approval.
</Tip>


## OpenAPI

````yaml GET /v1/templates
openapi: 3.0.0
info:
  title: Keebai Public API
  description: Superficie pública REST autenticada con Personal Access Tokens (PAT).
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.keebai.com
    description: Production
security: []
tags: []
paths:
  /v1/templates:
    get:
      tags:
        - templates
      summary: Listar templates aprobados de la company
      operationId: PublicTemplatesController_list
      parameters:
        - name: page
          required: false
          in: query
          schema:
            default: 0
            type: number
        - name: limit
          required: false
          in: query
          schema:
            maximum: 100
            default: 50
            type: number
        - name: status
          required: false
          in: query
          schema:
            default: APPROVED
            type: string
            enum:
              - PENDING
              - IN_REVIEW
              - REJECTED
              - APPROVED
              - PAUSED
              - DISABLED
              - IN_APPEAL
        - name: channel_id
          required: false
          in: query
          schema:
            type: string
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedTemplatesResponse'
      security:
        - PAT: []
components:
  schemas:
    PaginatedTemplatesResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/PublicTemplateDto'
        page:
          type: number
        limit:
          type: number
        total:
          type: number
      required:
        - items
        - page
        - limit
        - total
    PublicTemplateDto:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        language:
          type: string
        status:
          type: string
        category:
          type: string
        parameter_format:
          type: string
        variables:
          type: array
          items:
            type: string
      required:
        - id
        - name
        - language
        - status
        - category
        - variables
  securitySchemes:
    PAT:
      scheme: bearer
      bearerFormat: kbai_pk_<hex>
      type: http
      description: >-
        Personal Access Token con prefijo `kbai_pk_`. Generar desde el portal
        con permiso `developer.manage_tokens`.

````