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

# Crear Plantilla

> Crea una nueva plantilla HSM y envíala a WhatsApp para aprobación

Crea plantillas HSM personalizadas con parámetros de posición, botones interactivos y medios. Opcionalmente, envía la plantilla directamente a WhatsApp para aprobación.

```
POST /v1/bots/{botId}/templates
```

<Tip>
  Las **plantillas** deben ser aprobadas por el equipo de WhatsApp antes de poder usarlas. Sigue las pautas de Meta para evitar rechazos.
</Tip>

***

## Parámetros de ruta

| Propiedad | Tipo   | Descripción                            |
| --------- | ------ | -------------------------------------- |
| **botId** | string | ID único del bot. Ejemplo: `123456789` |

***

## Parámetros de consulta

| Propiedad        | Tipo    | Descripción                                                            |
| ---------------- | ------- | ---------------------------------------------------------------------- |
| **sendToAprove** | boolean | Define si la plantilla debe ser enviada a WhatsApp para su aprobación. |

***

## Cuerpo de la solicitud

| Propiedad             | Tipo    | Descripción                                                                                                                                                   |
| --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **category**          | string  | Categoría de la plantilla HSM. Valores: `UTILITY`, `MARKETING`, `AUTHENTICATION`                                                                              |
| **language**          | string  | Idioma de la plantilla.                                                                                                                                       |
| **isVisible**         | boolean | Define si la plantilla debe ser mostrada a los operadores.                                                                                                    |
| **params**            | array   | Estructura de parámetros. Para la categoría de autenticación, Meta ha restringido a un parámetro.                                                             |
| **paramsNumber**      | number  | Número de parámetros. Para la categoría de autenticación, Meta ha restringido a un parámetro.                                                                 |
| **elementName**       | string  | Identificador único de la plantilla. Solo puede contener letras minúsculas, guiones bajos (`_`) y números.                                                    |
| **displayName**       | string  | Nombre para mostrar de la plantilla.                                                                                                                          |
| **template**          | string  | Cuerpo de la plantilla. Para la categoría de autenticación, Meta ha restringido el contenido.                                                                 |
| **type**              | string  | Tipo de HSM. Valores: `HSM`, `IMAGE`, `VIDEO`, `DOCUMENT`                                                                                                     |
| **mediaUrl**          | string  | URL del medio. Requerido cuando el tipo de HSM es `IMAGE`, `VIDEO`, `DOCUMENT`. No aplicable para la categoría de autenticación.                              |
| **interactiveAction** | string  | Acción interactiva del HSM. Valores: `NONE`, `CALL_TO_ACTION`, `QUICK_REPLY`, `OTP`                                                                           |
| **buttons**           | array   | Estructura del botón. Requerido cuando la acción interactiva del HSM es `CALL_TO_ACTION`, `QUICK_REPLY` o `OTP`.                                              |
| **header**            | string  | Encabezado de la plantilla. Aplicable solo para plantillas de tipo texto. No aplicable para la categoría de autenticación y tiene un límite de 60 caracteres. |
| **exampleHeader**     | string  | Ejemplo del encabezado. Obligatorio solo si la plantilla tendrá un encabezado.                                                                                |
| **headerParams**      | array   | Estructura de parámetros. El encabezado admite un máximo de un parámetro.                                                                                     |
| **example**           | string  | Ejemplo de la plantilla. Si la plantilla tiene un parámetro, este debe ser reemplazado con un ejemplo.                                                        |
| **extraSettings**     | object  | Configuraciones opcionales para la plantilla.                                                                                                                 |

***

## Ejemplos de solicitud

<AccordionGroup>
  <Accordion title="Texto">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.jelou.ai/v1/bots/BOT_ID/templates?sendToAprove=true' \
      --header 'Authorization: Basic {{Base64EncodedUsername:Password}}' \
      --header 'Content-Type: application/json' \
      --data '{
        "displayName": "plantilla_texto_utility",
        "template": "Gracias por tu pedido, {{1}}! Tu número de confirmación es {{2}}. Si tienes alguna pregunta, contacta a soporte.",
        "example": "Gracias por tu pedido, María! Tu número de confirmación es 71936. Si tienes alguna pregunta, contacta a soporte.",
        "elementName": "plantilla_texto_utility",
        "params": [
          {"param": "1", "label": "cliente", "example": "María"},
          {"param": "2", "label": "orden", "example": "71936"}
        ],
        "paramsNumber": 2,
        "type": "HSM",
        "language": "es",
        "category": "UTILITY",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>

  <Accordion title="Texto con botones de respuesta rápida">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.jelou.ai/v1/bots/BOT_ID/templates?sendToAprove=true' \
      --header 'Authorization: Basic {{Base64EncodedUsername:Password}}' \
      --header 'Content-Type: application/json' \
      --data '{
        "displayName": "plantilla_quick_reply",
        "template": "Gracias por tu pedido, {{1}}! Tu número de confirmación es {{2}}. Usa los botones para contactarnos.",
        "example": "Gracias por tu pedido, María! Tu número de confirmación es 57893. Usa los botones para contactarnos.",
        "elementName": "plantilla_quick_reply",
        "params": [
          {"param": "1", "label": "cliente", "example": "María"},
          {"param": "2", "label": "orden", "example": "57893"}
        ],
        "paramsNumber": 2,
        "type": "HSM",
        "language": "es",
        "category": "UTILITY",
        "interactiveAction": "QUICK_REPLY",
        "buttons": [
          {"text": "Contactar Soporte", "type": "QUICK_REPLY"},
          {"text": "Contactar Ventas", "type": "QUICK_REPLY"}
        ]
      }'
    ```
  </Accordion>

  <Accordion title="Texto con botones CTA">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.jelou.ai/v1/bots/BOT_ID/templates?sendToAprove=true' \
      --header 'Authorization: Basic {{Base64EncodedUsername:Password}}' \
      --header 'Content-Type: application/json' \
      --data '{
        "displayName": "plantilla_call_action",
        "template": "Gracias por tu pedido, {{1}}! Tu número de confirmación es {{2}}. Usa los botones para contactarnos.",
        "example": "Gracias por tu pedido, María! Tu número de confirmación es 67996. Usa los botones para contactarnos.",
        "elementName": "plantilla_call_action",
        "params": [
          {"param": "1", "label": "cliente", "example": "María"},
          {"param": "2", "label": "orden", "example": "67996"}
        ],
        "paramsNumber": 2,
        "type": "HSM",
        "language": "es",
        "category": "UTILITY",
        "interactiveAction": "CALL_TO_ACTION",
        "buttons": [
          {"text": "Contactar Soporte", "type": "URL", "url": "https://apps.jelou.ai", "example": "https://apps.jelou.ai"},
          {"text": "Llamar", "type": "PHONE_NUMBER", "phone_number": "+PHONE_NUMBER"}
        ]
      }'
    ```
  </Accordion>

  <Accordion title="Imagen">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.jelou.ai/v1/bots/BOT_ID/templates?sendToAprove=true' \
      --header 'Authorization: Basic {{Base64EncodedUsername:Password}}' \
      --header 'Content-Type: application/json' \
      --data '{
        "displayName": "plantilla_imagen",
        "template": "Hola {{1}}. Te invitamos a conocer nuestras promociones.",
        "example": "Hola María. Te invitamos a conocer nuestras promociones.",
        "elementName": "plantilla_imagen",
        "params": [
          {"param": "1", "label": "cliente", "example": "María"}
        ],
        "paramsNumber": 1,
        "type": "IMAGE",
        "language": "es",
        "category": "MARKETING",
        "mediaUrl": "https://cdn.ejemplo.com/imagen.jpeg",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>

  <Accordion title="Documento">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.jelou.ai/v1/bots/BOT_ID/templates?sendToAprove=true' \
      --header 'Authorization: Basic {{Base64EncodedUsername:Password}}' \
      --header 'Content-Type: application/json' \
      --data '{
        "displayName": "plantilla_documento",
        "template": "Hola {{1}}. Adjuntamos tu documento solicitado.",
        "example": "Hola María. Adjuntamos tu documento solicitado.",
        "elementName": "plantilla_documento",
        "params": [
          {"param": "1", "label": "cliente", "example": "María"}
        ],
        "paramsNumber": 1,
        "type": "DOCUMENT",
        "language": "es",
        "category": "MARKETING",
        "mediaUrl": "https://cdn.ejemplo.com/documento.pdf",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>

  <Accordion title="Video">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.jelou.ai/v1/bots/BOT_ID/templates?sendToAprove=true' \
      --header 'Authorization: Basic {{Base64EncodedUsername:Password}}' \
      --header 'Content-Type: application/json' \
      --data '{
        "displayName": "plantilla_video",
        "template": "Hola {{1}}. Mira nuestro nuevo video.",
        "example": "Hola María. Mira nuestro nuevo video.",
        "elementName": "plantilla_video",
        "params": [
          {"param": "1", "label": "cliente", "example": "María"}
        ],
        "paramsNumber": 1,
        "type": "VIDEO",
        "language": "es",
        "category": "MARKETING",
        "mediaUrl": "https://cdn.ejemplo.com/video.mp4",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>
</AccordionGroup>

***

## Respuestas

<AccordionGroup>
  <Accordion title="200 - Respuesta exitosa">
    ```json theme={null}
    {
      "message": ["Template has been created."],
      "status": "success",
      "data": {
        "template": "¡Hola! Somos *Jelou*. \nTe damos la bienvenida _{{1}}_. Pronto {{2}} del equipo se comunicará contigo.",
        "displayName": "Bienvenida",
        "elementName": "test_hsm_api",
        "params": [
          {"label": "Nombre del cliente", "param": "1"},
          {"label": "Nombre del asesor", "param": "2"}
        ],
        "paramsNumber": 2,
        "isVisible": false,
        "language": "ES",
        "createdAt": "2021-01-28T15:08:38.492Z",
        "updatedAt": "2021-01-28T15:08:38.492Z",
        "botId": "BOT_ID",
        "companyId": 100,
        "status": "APPROVED"
      }
    }
    ```
  </Accordion>

  <Accordion title="400 - Bad Request">
    ```json theme={null}
    {
      "message": ["Template name already exists"],
      "status": "failed"
    }
    ```
  </Accordion>

  <Accordion title="401 - Unauthorized">
    ```json theme={null}
    {
      "message": "Authentication failed"
    }
    ```
  </Accordion>

  <Accordion title="404 - Not Found">
    ```json theme={null}
    {
      "message": ["The Bot could not be found at the moment."],
      "statusMessage": "failed",
      "error": {
        "code": "E1019",
        "key": "BOT_NOT_FOUND"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

<Note>
  El campo `status` en la respuesta indica si tu plantilla ha sido aprobada por WhatsApp.
</Note>

***

## Idioma

El idioma soportado por WhatsApp está detallado en la página oficial. Por favor, revísalo cuidadosamente en el [siguiente enlace](https://developers.facebook.com/docs/whatsapp/api/messages/message-templates#supported-languages-).

***

## Restricciones de contenido (Categoría de Autenticación)

Meta ha restringido el contenido para la categoría de autenticación. El contenido será según el idioma de la plantilla. Meta está restringido a un solo parámetro.

### Idioma

| Idioma             | Código | Contenido                             |
| ------------------ | ------ | ------------------------------------- |
| **Inglés**         | en     | `{{1}}` is your verification code.    |
| **Portugués (BR)** | pt\_BR | Seu código de verificação é `{{1}}`.  |
| **Español**        | es     | Tu código de verificación es `{{1}}`. |

***

## Estructura de los parámetros

Usa la siguiente estructura en el campo de `params` al crear una plantilla:

```json theme={null}
[
  {"label": "Nombre del cliente", "param": "1"},
  {"label": "Número de orden", "param": "2"}
]
```

***

## Estructura del botón

Utiliza la siguiente estructura en el campo de `buttons` cuando las acciones interactivas sean `CALL_TO_ACTION`, `QUICK_REPLY` o `OTP`.

### QUICK\_REPLY

Se utiliza para obtener respuestas rápidas. Es un arreglo de objetos y puede tener un máximo de 3 botones.

| Propiedad | Descripción                                           |
| --------- | ----------------------------------------------------- |
| **text**  | Texto del botón, este valor no puede ser actualizado. |
| **type**  | Tipo de botón. Valor: `QUICK_REPLY`                   |

```json theme={null}
[
  {"text": "Más información", "type": "QUICK_REPLY"},
  {"text": "Hablar con operador", "type": "QUICK_REPLY"},
  {"text": "Ventas", "type": "QUICK_REPLY"}
]
```

### CALL\_TO\_ACTION

Se utiliza para ofrecer una llamada a la acción. Puede tener un máximo de 2 botones y un máximo de 1 botón de cada tipo.

| Propiedad         | Descripción                                                    |
| ----------------- | -------------------------------------------------------------- |
| **text**          | Texto del botón, este valor no puede ser actualizado.          |
| **type**          | Tipo de botón. Valores: `PHONE_NUMBER`, `URL`                  |
| **phone\_number** | Número de teléfono del botón.                                  |
| **url**           | URL del botón.                                                 |
| **example**       | Ejemplo de la URL. Requerido cuando el tipo de botón es `URL`. |

```json theme={null}
[
  {"text": "Ventas", "phone_number": "+PHONE_NUMBER", "type": "PHONE_NUMBER"},
  {"type": "URL", "text": "Ver sitio", "url": "https://apps.jelou.ai/{{1}}", "example": "https://apps.jelou.ai/ofertas"}
]
```

### OTP

Se utiliza para obtener una "Contraseña de un solo uso" (One Time Password). Puede tener un máximo de 1 botón.

| Propiedad | Descripción                                           |
| --------- | ----------------------------------------------------- |
| **text**  | Texto del botón, este valor no puede ser actualizado. |
| **type**  | Tipo de botón. Valor: `OTP`                           |

```json theme={null}
[
  {"text": "COPY CODE", "type": "OTP"}
]
```

***

## Estructura de extraSettings

| Propiedad                     | Tipo    | Descripción                                                                                                |
| ----------------------------- | ------- | ---------------------------------------------------------------------------------------------------------- |
| **addSecurityRecommendation** | boolean | Añade un mensaje de seguridad adicional en las plantillas de autenticación.                                |
| **codeExpirationMinutes**     | number  | Añade un mensaje en el pie de página con el tiempo de expiración del código. Valores entre 1 y 90 minutos. |
| **allowChangeCategory**       | boolean | Permite que Meta actualice la categoría de la plantilla si es necesario.                                   |


## OpenAPI

````yaml POST /v1/bots/{botId}/templates
openapi: 3.1.0
info:
  title: Jelou API
  description: >-
    API for the Jelou platform. Send messages, manage campaigns, handle
    conversations, users, databases, and widgets.
  version: 1.0.0
servers:
  - url: https://api.jelou.ai
    description: Production server
security:
  - basicAuth: []
tags:
  - name: Messages
    description: Send messages to users
  - name: Campaigns
    description: HSM campaigns and templates
  - name: Conversations
    description: Chat history and metrics
  - name: Users
    description: User state and cache management
  - name: Resources
    description: Media resource management
  - name: Datum
    description: Database CRUD operations
  - name: Widget
    description: Widget and room management
  - name: PMA Custom
    description: External support panel integration
paths:
  /v1/bots/{botId}/templates:
    post:
      tags:
        - Campaigns
      summary: Crear Plantilla
      description: >-
        Crea una nueva plantilla HSM y opcionalmente envíala a WhatsApp para
        aprobación.
      operationId: createTemplate
      parameters:
        - name: botId
          in: path
          required: true
          schema:
            type: string
        - name: sendToAprove
          in: query
          schema:
            type: boolean
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTemplateRequest'
      responses:
        '200':
          description: Plantilla creada exitosamente
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemplateResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  schemas:
    CreateTemplateRequest:
      type: object
      required:
        - elementName
        - template
        - category
        - language
      properties:
        category:
          type: string
          enum:
            - UTILITY
            - MARKETING
            - AUTHENTICATION
        language:
          type: string
        isVisible:
          type: boolean
        params:
          type: array
          items:
            $ref: '#/components/schemas/TemplateParam'
        paramsNumber:
          type: integer
        elementName:
          type: string
          pattern: ^[a-z0-9_]+$
        displayName:
          type: string
        template:
          type: string
        type:
          type: string
          enum:
            - HSM
            - IMAGE
            - VIDEO
            - DOCUMENT
        mediaUrl:
          type: string
          format: uri
        interactiveAction:
          type: string
          enum:
            - NONE
            - CALL_TO_ACTION
            - QUICK_REPLY
            - OTP
        buttons:
          type: array
          items:
            $ref: '#/components/schemas/TemplateButton'
        header:
          type: string
          maxLength: 60
        exampleHeader:
          type: string
        headerParams:
          type: array
          items:
            type: object
        example:
          type: string
        extraSettings:
          $ref: '#/components/schemas/TemplateExtraSettings'
    TemplateResponse:
      type: object
      properties:
        message:
          type: array
          items:
            type: string
        status:
          type: string
        data:
          type: object
    TemplateParam:
      type: object
      properties:
        param:
          type: string
        label:
          type: string
        example:
          type: string
    TemplateButton:
      type: object
      properties:
        text:
          type: string
        type:
          type: string
          enum:
            - QUICK_REPLY
            - URL
            - PHONE_NUMBER
            - OTP
        url:
          type: string
        phone_number:
          type: string
        example:
          type: string
    TemplateExtraSettings:
      type: object
      properties:
        addSecurityRecommendation:
          type: boolean
        codeExpirationMinutes:
          type: integer
          minimum: 1
          maximum: 90
        allowChangeCategory:
          type: boolean
    Error:
      type: object
      properties:
        message:
          oneOf:
            - type: string
            - type: array
              items:
                type: string
        statusMessage:
          type: string
        status:
          type: integer
        error:
          type: object
          properties:
            code:
              type: string
            key:
              type: string
            description:
              type: string
            developerMessages:
              type: object
            clientMessages:
              type: object
        validationError:
          type: object
  responses:
    BadRequest:
      description: Bad request - Invalid format or missing required fields
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized - Invalid authentication credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Not found - Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: Basic authentication using Base64 encoded clientId:clientSecret

````