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

# Criar template

> Cria um template no escopo do número vinculado. O campo body aceita três formas: (1) um OBJETO estruturado { header?, body, footer?, buttons? } — recomendado; (2) esse mesmo JSON como STRING; ou (3) TEXTO PURO, embrulhado automaticamente em { "body": { "text": ... } }. Estrutura: header opcional NONE (padrão) | TEXT (0–1 variável, até 60 caracteres) | IMAGE | VIDEO | DOCUMENT — mídia informada por header.url (http/https) OU header.base64 (data URI data:<mime>;base64,…, re-hospedado no servidor); body.text até 1024 caracteres, com variáveis no estilo nomeado {{nome}} (não pode começar nem terminar com variável); footer.text até 60 caracteres, sem variáveis; buttons (até 10 no total) dos tipos QUICK_REPLY (≤ 10), URL (≤ 2; estática ou dinâmica com um {{1}} no fim da URL + example resolvido), PHONE_NUMBER (≤ 1) e COPY_CODE (≤ 1; o código vai em button.example) — misturar quick-reply com botões CTA é permitido. Botões podem acompanhar header de vídeo ou documento (PDF). O campo examples é OBRIGATÓRIO quando o body/header (ou a URL dinâmica) usam variáveis: um objeto mapeando cada variável a um valor de amostra; faltando → 400 { code: "TEMPLATE_EXAMPLES_REQUIRED", details: { missing: [...] } }. Para números Meta o template é submetido à Meta para aprovação (metaStatus PENDING); 400 META_TEMPLATE_SUBMIT_FAILED se a Meta recusar. 409 se já existir um template com esse nome. Requer key escopada a número.

**Requer uma chave com escopo de número.**



## OpenAPI

````yaml openapi.pt.json POST /v1/templates
openapi: 3.1.0
info:
  title: API Pilot Status
  version: 1.0.0
  license:
    name: Pilot Status Terms of Service
    url: https://pilotstatus.com.br/terms
  description: >-
    API REST pública do Pilot Status. Autentique com o header `x-api-key:
    ps_...` (ou `x-api-key-id`). Base URL: https://pilotstatus.com.br
servers:
  - url: https://pilotstatus.com.br
security:
  - apiKey: []
  - apiKeyId: []
paths:
  /v1/templates:
    post:
      tags:
        - Templates
      summary: Criar template
      description: >-
        Cria um template no escopo do número vinculado. O campo body aceita três
        formas: (1) um OBJETO estruturado { header?, body, footer?, buttons? } —
        recomendado; (2) esse mesmo JSON como STRING; ou (3) TEXTO PURO,
        embrulhado automaticamente em { "body": { "text": ... } }. Estrutura:
        header opcional NONE (padrão) | TEXT (0–1 variável, até 60 caracteres) |
        IMAGE | VIDEO | DOCUMENT — mídia informada por header.url (http/https)
        OU header.base64 (data URI data:<mime>;base64,…, re-hospedado no
        servidor); body.text até 1024 caracteres, com variáveis no estilo
        nomeado {{nome}} (não pode começar nem terminar com variável);
        footer.text até 60 caracteres, sem variáveis; buttons (até 10 no total)
        dos tipos QUICK_REPLY (≤ 10), URL (≤ 2; estática ou dinâmica com um
        {{1}} no fim da URL + example resolvido), PHONE_NUMBER (≤ 1) e COPY_CODE
        (≤ 1; o código vai em button.example) — misturar quick-reply com botões
        CTA é permitido. Botões podem acompanhar header de vídeo ou documento
        (PDF). O campo examples é OBRIGATÓRIO quando o body/header (ou a URL
        dinâmica) usam variáveis: um objeto mapeando cada variável a um valor de
        amostra; faltando → 400 { code: "TEMPLATE_EXAMPLES_REQUIRED", details: {
        missing: [...] } }. Para números Meta o template é submetido à Meta para
        aprovação (metaStatus PENDING); 400 META_TEMPLATE_SUBMIT_FAILED se a
        Meta recusar. 409 se já existir um template com esse nome. Requer key
        escopada a número.


        **Requer uma chave com escopo de número.**
      operationId: post_templates
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: >-
                    Nome do template (apenas letras/números; separadores viram
                    _).
                  example: promo_cupom
                body:
                  type: string
                  description: >-
                    Conteúdo do template: objeto { header?, body, footer?,
                    buttons? } (recomendado), o mesmo JSON como string, ou texto
                    puro (embrulhado automaticamente).
                  example: '{ "body": { "text": "Oi {{nome}}!" } }'
                body.header:
                  type: string
                  description: >-
                    Cabeçalho opcional. TEXT: text com 0–1 variável (até 60
                    caracteres). IMAGE/VIDEO/DOCUMENT: informe url (http/https)
                    OU base64 (data URI); base64 é re-hospedado no servidor. Sem
                    cabeçalho de localização.
                  example: '{ "type": "IMAGE", "base64": "data:image/png;base64,..." }'
                body.footer:
                  type: string
                  description: Rodapé opcional, até 60 caracteres, sem variáveis.
                  example: '{ "text": "Promoção por tempo limitado" }'
                body.buttons:
                  type: string
                  description: >-
                    Até 10 botões: QUICK_REPLY (≤ 10; text), URL (≤ 2; text +
                    url estática ou dinâmica com {{1}} no fim), PHONE_NUMBER (≤
                    1; text + phone_number E.164), COPY_CODE (≤ 1; código em
                    example). Quick-reply e CTA podem coexistir.
                  example: >-
                    [{ "type": "URL", "text": "Comprar", "url":
                    "https://loja.com/promo/{{link}}" }, { "type": "COPY_CODE",
                    "example": ["PROMO10"] }]
                examples:
                  type: string
                  description: >-
                    Obrigatório quando há variáveis: mapeia cada variável usada
                    no body/header (e na URL dinâmica) a um valor de amostra. O
                    código do COPY_CODE vai em button.example, não aqui.
                    Faltando → 400 TEMPLATE_EXAMPLES_REQUIRED.
                  example: '{ "nome": "Maria", "desconto": "10%", "link": "abc123" }'
                category:
                  type: string
                  description: Categoria do template (padrão UTILITY).
                  example: MARKETING
                language:
                  type: string
                  description: Idioma do template (padrão pt_BR).
                  example: pt_BR
              required:
                - name
                - body
            example:
              name: promo_cupom
              category: MARKETING
              language: pt_BR
              body:
                header:
                  type: IMAGE
                  base64: data:image/png;base64,...
                body:
                  text: Oi {{nome}}! Use e ganhe {{desconto}} de desconto.
                footer:
                  text: Promoção por tempo limitado
                buttons:
                  - type: QUICK_REPLY
                    text: Quero!
                  - type: URL
                    text: Comprar
                    url: https://loja.com/promo/{{link}}
                  - type: PHONE_NUMBER
                    text: Falar
                    phone_number: '+5511999998888'
                  - type: COPY_CODE
                    example:
                      - PROMO10
              examples:
                nome: Maria
                desconto: 10%
                link: abc123
      responses:
        '201':
          description: Criar template completo
          content:
            application/json:
              example:
                id: tpl_01HZX...
                name: promo_cupom
                category: MARKETING
                metaStatus: PENDING
        '400':
          description: Faltando examples
          content:
            application/json:
              example:
                code: TEMPLATE_EXAMPLES_REQUIRED
                details:
                  missing:
                    - nome
        '401':
          description: Header `x-api-key` / `x-api-key-id` ausente ou inválido
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Unauthorized
        '403':
          description: Chave com escopo de tenant usada em endpoint com escopo de número
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Tenant-scoped keys cannot call number endpoints
                code: TENANT_SCOPE_NOT_ALLOWED
        '429':
          description: Limite de taxa excedido
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  code:
                    type: string
              example:
                error: Too many requests
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: Sua chave de API ps_
    apiKeyId:
      type: apiKey
      in: header
      name: x-api-key-id
      description: Id da chave de API (alternativa ao x-api-key)

````