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

# List message templates

> Returns the templates you can send, from Kai's mirror of the
channel's library. A template is sendable when Meta approved it and
all of its variables are plain text. A template with an image header
or with a variable link in a button is not sendable.

**Titles.** A template can have a title above the message, and the
title can have its own variables. Kai fills them. WhatsApp numbers
and names the variables of the title and of the message separately,
so `{{1}}` in the title and `{{1}}` in the message are two values.
To keep them apart, each variable has an address: a message variable
keeps its plain name, and a title variable gets `header.` in front of
it. The `variables` field lists these addresses in the order that a
send fills them, the title first.

Omit `channel_id` when the workspace has one WhatsApp channel. Send
`status=all` to also see pending and rejected templates.

**Hints.** Each variable carries a `binding` and a `value`. Send
`agent` and one of `contact_id` or `phone` to fill the values, then
prefill your own form with them. A `value` of `null` means that Kai
cannot fill this variable. Ask the person for it.

The hints are advice. `POST /conversations/outbound` still needs
every value, because your form is what the person reads before the
message goes out. Your user can also change a filled value.




## OpenAPI

````yaml /openapi.yaml get /templates
openapi: 3.1.0
info:
  title: Kai API
  version: 1.1.0
  description: |
    Push, update, assign and export the contacts of one Kai workspace. Read
    a contact's conversations, list the approved WhatsApp templates, send a
    template message to a customer, and assign the conversation to a
    teammate.

    Every request needs an API key. Make a key in Kai, under
    **Settings → API**. Send the key in the `Authorization` header.

    The API works on one workspace. The key decides which workspace, so no
    request carries a workspace id.
  contact:
    name: Kai support
    url: https://kaisupport.com
servers:
  - url: https://kaisupport.com/api/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Contacts
    description: Customer profiles, their attributes and their account owners.
  - name: Attributes
    description: The attributes that the workspace keeps on every contact.
  - name: Members
    description: The teammates of the workspace. Read-only.
  - name: Conversations
    description: A contact's message threads, and who they are assigned to.
  - name: Templates
    description: The approved WhatsApp message templates of a channel.
  - name: Channels
    description: The connected messaging channels. Read-only.
paths:
  /templates:
    get:
      tags:
        - Templates
      summary: List message templates
      description: |
        Returns the templates you can send, from Kai's mirror of the
        channel's library. A template is sendable when Meta approved it and
        all of its variables are plain text. A template with an image header
        or with a variable link in a button is not sendable.

        **Titles.** A template can have a title above the message, and the
        title can have its own variables. Kai fills them. WhatsApp numbers
        and names the variables of the title and of the message separately,
        so `{{1}}` in the title and `{{1}}` in the message are two values.
        To keep them apart, each variable has an address: a message variable
        keeps its plain name, and a title variable gets `header.` in front of
        it. The `variables` field lists these addresses in the order that a
        send fills them, the title first.

        Omit `channel_id` when the workspace has one WhatsApp channel. Send
        `status=all` to also see pending and rejected templates.

        **Hints.** Each variable carries a `binding` and a `value`. Send
        `agent` and one of `contact_id` or `phone` to fill the values, then
        prefill your own form with them. A `value` of `null` means that Kai
        cannot fill this variable. Ask the person for it.

        The hints are advice. `POST /conversations/outbound` still needs
        every value, because your form is what the person reads before the
        message goes out. Your user can also change a filled value.
      operationId: listTemplates
      parameters:
        - name: channel_id
          in: query
          description: A WhatsApp channel id from `GET /channels`.
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          description: Send `all` to include templates that are not sendable.
          schema:
            type: string
            enum:
              - all
        - name: agent
          in: query
          description: |
            The email address or the member id of the teammate who sends the
            message. It fills the `agent_name` bindings. An address that no
            member holds returns `agent: null` and empty hints.
          schema:
            type: string
        - name: contact_id
          in: query
          description: A contact id. It fills the `customer_name` bindings.
          schema:
            type: string
            format: uuid
        - name: phone
          in: query
          description: |
            A phone number, as an alternative to `contact_id`. Kai finds the
            contact of this number.
          schema:
            type: string
        - name: contact_name
          in: query
          description: |
            The name that your own system holds for this customer. It wins
            over the name in Kai, and it fills a `customer_first_name`
            binding for a customer that Kai does not know yet.
          schema:
            type: string
      responses:
        '200':
          description: The channel's templates.
          content:
            application/json:
              schema:
                type: object
                properties:
                  channel_id:
                    type: string
                    format: uuid
                  agent:
                    type:
                      - object
                      - 'null'
                    description: >-
                      The teammate that `agent` named, or `null` when Kai did
                      not recognize it.
                    properties:
                      member_id:
                        type: string
                        format: uuid
                      name:
                        type:
                          - string
                          - 'null'
                      email:
                        type:
                          - string
                          - 'null'
                  contact:
                    type:
                      - object
                      - 'null'
                    description: The contact behind `contact_id` or `phone`, or `null`.
                    properties:
                      contact_id:
                        type:
                          - string
                          - 'null'
                        format: uuid
                      name:
                        type:
                          - string
                          - 'null'
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Template'
              example:
                channel_id: 7c1f4a80-2b6e-4f5d-9a3c-8e2d1b0c9f44
                agent:
                  member_id: 2c9a0d51-6f4b-4b0d-8f2a-1d3c5e7a9b11
                  name: Baran Demir
                  email: baran@example.com
                contact:
                  contact_id: 4f1d6f2a-6a1e-4a0b-9c53-2a9a1f0c77d1
                  name: Gülsüm Bodur
                data:
                  - name: consultation_request_cant_be_reached_reschedule_tr
                    language: tr
                    category: UTILITY
                    status: approved
                    header: Derece Kampüsü · {{konu}}
                    body: >-
                      Selamlar {{customer_name}} ben Derece Kampüsü’nden
                      {{consultant_name}}, ön görüşme talep etmişsin ancak sana
                      ulaşamadım.
                    variables:
                      - header.konu
                      - customer_name
                      - consultant_name
                    variable_hints:
                      - address: header.konu
                        key: konu
                        part: header
                        binding: free
                        value: null
                        source: null
                      - address: customer_name
                        key: customer_name
                        part: body
                        binding: customer_name
                        value: Gülsüm Bodur
                        source: contact
                      - address: consultant_name
                        key: consultant_name
                        part: body
                        binding: agent_name
                        value: Baran Demir
                        source: member
                    sendable: true
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  schemas:
    Template:
      type: object
      required:
        - name
        - language
        - status
        - header
        - body
        - variables
        - sendable
      properties:
        name:
          type: string
        language:
          type: string
          description: Meta's language code, such as `tr` or `en_US`.
        category:
          type: string
          description: Meta's category, such as `UTILITY` or `MARKETING`.
        status:
          type: string
          description: Meta's review status. Only `approved` templates send.
        header:
          type:
            - string
            - 'null'
          description: |
            The title above the message, with its placeholders, or `null`.
            WhatsApp shows the title in bold on the first line.
        body:
          type: string
          description: The message text, with its `{{1}}` placeholders.
        variables:
          type: array
          items:
            type: string
          description: |
            The addresses of the variables, in the order that
            `template.variables` fills them: the title first, then the
            message. A message variable keeps its plain name
            (`customer_name`). A title variable has `header.` in front of it
            (`header.konu`).
        variable_hints:
          type: array
          description: One entry per variable, in the same order as `variables`.
          items:
            $ref: '#/components/schemas/VariableHint'
        sendable:
          type: boolean
    VariableHint:
      type: object
      required:
        - address
        - key
        - part
        - binding
        - value
        - source
      properties:
        address:
          type: string
          description: |
            The name to use in the object form of `template.variables`.
        key:
          type: string
          description: |
            The placeholder as the template spells it. The title and the
            message can spell one the same, which is why `address` exists.
        part:
          type: string
          enum:
            - header
            - body
          description: Where the variable is. `header` is the title, `body` is the message.
        binding:
          type: string
          enum:
            - free
            - agent_name
            - agent_first_name
            - agent_last_name
            - customer_name
            - customer_first_name
            - customer_last_name
          description: |
            Where this variable gets its value. `free` means that a person
            types it. The workspace configures a binding under
            **Settings → Channels**. Kai guesses a binding from the name of
            the variable when nobody configured one.
        value:
          type:
            - string
            - 'null'
          description: |
            The value that Kai can fill. `null` means that Kai cannot fill
            it: the binding is `free`, or the source is empty, or you did
            not send `agent`, `contact_id` or `phone`.
        source:
          type:
            - string
            - 'null'
          enum:
            - contact
            - member
            - request
            - null
          description: |
            Where the value comes from. `contact` is the contact record in
            Kai. `member` is the profile of the teammate. `request` is the
            `contact_name` that you sent.
    Error:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorBody'
    ErrorBody:
      type: object
      properties:
        type:
          type: string
          description: A stable machine name for the error.
        message:
          type: string
          description: One sentence for a human reader.
        details:
          description: The attributes or the identities that caused the error.
  responses:
    BadRequest:
      description: Kai could not read the request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: invalid_request
              message: >-
                Send at least one of "external_id", "email", "phone" or
                "identities" so the contact can be matched.
    Unauthorized:
      description: The API key is missing or not valid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: unauthorized
              message: That API key is not valid.
    Forbidden:
      description: The API key does not have the permission that this endpoint needs.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: forbidden
              message: This key does not have the "contacts:write" permission.
    NotFound:
      description: There is no such record in this workspace.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              type: not_found
              message: No such contact.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        Send your API key as `Authorization: Bearer kai_live_...`.

        Make, edit and revoke keys in Kai, under **Settings → API**. Kai stores
        only a hash of the key, so the full key is shown one time. You can
        change the name and the permissions of a key later without a new key.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.