> ## 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.

# Create Template

> Create a new HSM template and submit it to WhatsApp for approval

Create custom HSM templates with positional parameters, interactive buttons, and media. Optionally, submit the template directly to WhatsApp for approval.

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

<Tip>
  **Templates** must be approved by the WhatsApp team before they can be used. Follow Meta's guidelines to avoid rejections.
</Tip>

***

## Path Parameters

| Property  | Type   | Description                         |
| --------- | ------ | ----------------------------------- |
| **botId** | string | Unique bot ID. Example: `123456789` |

***

## Query Parameters

| Property         | Type    | Description                                                                |
| ---------------- | ------- | -------------------------------------------------------------------------- |
| **sendToAprove** | boolean | Defines whether the template should be submitted to WhatsApp for approval. |

***

## Request Body

| Property              | Type    | Description                                                                                                                            |
| --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **category**          | string  | HSM template category. Values: `UTILITY`, `MARKETING`, `AUTHENTICATION`                                                                |
| **language**          | string  | Template language.                                                                                                                     |
| **isVisible**         | boolean | Defines whether the template should be shown to operators.                                                                             |
| **params**            | array   | Parameter structure. For the authentication category, Meta has restricted to one parameter.                                            |
| **paramsNumber**      | number  | Number of parameters. For the authentication category, Meta has restricted to one parameter.                                           |
| **elementName**       | string  | Unique identifier for the template. Can only contain lowercase letters, underscores (`_`), and numbers.                                |
| **displayName**       | string  | Display name of the template.                                                                                                          |
| **template**          | string  | Template body. For the authentication category, Meta has restricted the content.                                                       |
| **type**              | string  | HSM type. Values: `HSM`, `IMAGE`, `VIDEO`, `DOCUMENT`                                                                                  |
| **mediaUrl**          | string  | Media URL. Required when the HSM type is `IMAGE`, `VIDEO`, `DOCUMENT`. Not applicable for the authentication category.                 |
| **interactiveAction** | string  | HSM interactive action. Values: `NONE`, `CALL_TO_ACTION`, `QUICK_REPLY`, `OTP`                                                         |
| **buttons**           | array   | Button structure. Required when the HSM interactive action is `CALL_TO_ACTION`, `QUICK_REPLY`, or `OTP`.                               |
| **header**            | string  | Template header. Applicable only for text-type templates. Not applicable for the authentication category and has a 60-character limit. |
| **exampleHeader**     | string  | Header example. Required only if the template will have a header.                                                                      |
| **headerParams**      | array   | Parameter structure. The header supports a maximum of one parameter.                                                                   |
| **example**           | string  | Template example. If the template has a parameter, it must be replaced with an example.                                                |
| **extraSettings**     | object  | Optional settings for the template.                                                                                                    |

***

## Request Examples

<AccordionGroup>
  <Accordion title="Text">
    ```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": "text_template_utility",
        "template": "Thank you for your order, {{1}}! Your confirmation number is {{2}}. If you have any questions, contact support.",
        "example": "Thank you for your order, Maria! Your confirmation number is 71936. If you have any questions, contact support.",
        "elementName": "text_template_utility",
        "params": [
          {"param": "1", "label": "customer", "example": "Maria"},
          {"param": "2", "label": "order", "example": "71936"}
        ],
        "paramsNumber": 2,
        "type": "HSM",
        "language": "en",
        "category": "UTILITY",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>

  <Accordion title="Text with quick reply buttons">
    ```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": "template_quick_reply",
        "template": "Thank you for your order, {{1}}! Your confirmation number is {{2}}. Use the buttons to contact us.",
        "example": "Thank you for your order, Maria! Your confirmation number is 57893. Use the buttons to contact us.",
        "elementName": "template_quick_reply",
        "params": [
          {"param": "1", "label": "customer", "example": "Maria"},
          {"param": "2", "label": "order", "example": "57893"}
        ],
        "paramsNumber": 2,
        "type": "HSM",
        "language": "en",
        "category": "UTILITY",
        "interactiveAction": "QUICK_REPLY",
        "buttons": [
          {"text": "Contact Support", "type": "QUICK_REPLY"},
          {"text": "Contact Sales", "type": "QUICK_REPLY"}
        ]
      }'
    ```
  </Accordion>

  <Accordion title="Text with CTA buttons">
    ```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": "template_call_action",
        "template": "Thank you for your order, {{1}}! Your confirmation number is {{2}}. Use the buttons to contact us.",
        "example": "Thank you for your order, Maria! Your confirmation number is 67996. Use the buttons to contact us.",
        "elementName": "template_call_action",
        "params": [
          {"param": "1", "label": "customer", "example": "Maria"},
          {"param": "2", "label": "order", "example": "67996"}
        ],
        "paramsNumber": 2,
        "type": "HSM",
        "language": "en",
        "category": "UTILITY",
        "interactiveAction": "CALL_TO_ACTION",
        "buttons": [
          {"text": "Contact Support", "type": "URL", "url": "https://apps.jelou.ai", "example": "https://apps.jelou.ai"},
          {"text": "Call", "type": "PHONE_NUMBER", "phone_number": "+PHONE_NUMBER"}
        ]
      }'
    ```
  </Accordion>

  <Accordion title="Image">
    ```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": "image_template",
        "template": "Hello {{1}}. We invite you to check out our promotions.",
        "example": "Hello Maria. We invite you to check out our promotions.",
        "elementName": "image_template",
        "params": [
          {"param": "1", "label": "customer", "example": "Maria"}
        ],
        "paramsNumber": 1,
        "type": "IMAGE",
        "language": "en",
        "category": "MARKETING",
        "mediaUrl": "https://cdn.example.com/image.jpeg",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>

  <Accordion title="Document">
    ```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": "document_template",
        "template": "Hello {{1}}. Please find your requested document attached.",
        "example": "Hello Maria. Please find your requested document attached.",
        "elementName": "document_template",
        "params": [
          {"param": "1", "label": "customer", "example": "Maria"}
        ],
        "paramsNumber": 1,
        "type": "DOCUMENT",
        "language": "en",
        "category": "MARKETING",
        "mediaUrl": "https://cdn.example.com/document.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": "video_template",
        "template": "Hello {{1}}. Watch our new video.",
        "example": "Hello Maria. Watch our new video.",
        "elementName": "video_template",
        "params": [
          {"param": "1", "label": "customer", "example": "Maria"}
        ],
        "paramsNumber": 1,
        "type": "VIDEO",
        "language": "en",
        "category": "MARKETING",
        "mediaUrl": "https://cdn.example.com/video.mp4",
        "interactiveAction": "NONE"
      }'
    ```
  </Accordion>
</AccordionGroup>

***

## Responses

<AccordionGroup>
  <Accordion title="200 - Successful response">
    ```json theme={null}
    {
      "message": ["Template has been created."],
      "status": "success",
      "data": {
        "template": "Hello! We are *Jelou*. \nWelcome _{{1}}_. Soon {{2}} from the team will reach out to you.",
        "displayName": "Welcome",
        "elementName": "test_hsm_api",
        "params": [
          {"label": "Customer name", "param": "1"},
          {"label": "Agent name", "param": "2"}
        ],
        "paramsNumber": 2,
        "isVisible": false,
        "language": "EN",
        "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>
  The `status` field in the response indicates whether your template has been approved by WhatsApp.
</Note>

***

## Language

The language supported by WhatsApp is detailed on the official page. Please review it carefully at the [following link](https://developers.facebook.com/docs/whatsapp/api/messages/message-templates#supported-languages-).

***

## Content Restrictions (Authentication Category)

Meta has restricted content for the authentication category. The content will be according to the template language. Meta is restricted to a single parameter.

### Language

| Language            | Code   | Content                               |
| ------------------- | ------ | ------------------------------------- |
| **English**         | en     | `{{1}}` is your verification code.    |
| **Portuguese (BR)** | pt\_BR | Seu código de verificação é `{{1}}`.  |
| **Spanish**         | es     | Tu código de verificación es `{{1}}`. |

***

## Parameter Structure

Use the following structure in the `params` field when creating a template:

```json theme={null}
[
  {"label": "Customer name", "param": "1"},
  {"label": "Order number", "param": "2"}
]
```

***

## Button Structure

Use the following structure in the `buttons` field when the interactive actions are `CALL_TO_ACTION`, `QUICK_REPLY`, or `OTP`.

### QUICK\_REPLY

Used to obtain quick replies. It is an array of objects and can have a maximum of 3 buttons.

| Property | Description                                |
| -------- | ------------------------------------------ |
| **text** | Button text, this value cannot be updated. |
| **type** | Button type. Value: `QUICK_REPLY`          |

```json theme={null}
[
  {"text": "More information", "type": "QUICK_REPLY"},
  {"text": "Talk to an operator", "type": "QUICK_REPLY"},
  {"text": "Sales", "type": "QUICK_REPLY"}
]
```

### CALL\_TO\_ACTION

Used to offer a call to action. Can have a maximum of 2 buttons and a maximum of 1 button of each type.

| Property          | Description                                          |
| ----------------- | ---------------------------------------------------- |
| **text**          | Button text, this value cannot be updated.           |
| **type**          | Button type. Values: `PHONE_NUMBER`, `URL`           |
| **phone\_number** | Button phone number.                                 |
| **url**           | Button URL.                                          |
| **example**       | URL example. Required when the button type is `URL`. |

```json theme={null}
[
  {"text": "Sales", "phone_number": "+PHONE_NUMBER", "type": "PHONE_NUMBER"},
  {"type": "URL", "text": "View site", "url": "https://apps.jelou.ai/{{1}}", "example": "https://apps.jelou.ai/offers"}
]
```

### OTP

Used to obtain a "One Time Password". Can have a maximum of 1 button.

| Property | Description                                |
| -------- | ------------------------------------------ |
| **text** | Button text, this value cannot be updated. |
| **type** | Button type. Value: `OTP`                  |

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

***

## extraSettings Structure

| Property                      | Type    | Description                                                                           |
| ----------------------------- | ------- | ------------------------------------------------------------------------------------- |
| **addSecurityRecommendation** | boolean | Adds an additional security message in authentication templates.                      |
| **codeExpirationMinutes**     | number  | Adds a footer message with the code expiration time. Values between 1 and 90 minutes. |
| **allowChangeCategory**       | boolean | Allows Meta to update the template category if necessary.                             |


## 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

````