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

# Enviar una plantilla de WhatsApp

> Envía una plantilla aprobada desde un número de tu organización. Dentro de las 24 horas desde el último mensaje entrante, las plantillas de texto sin botones ni cabeceras multimedia se envían como mensajes de texto libre; en los demás casos se envían como plantilla. Registra el mensaje en la conversación y aplica la política de tickets del canal. No asigna el ticket a un usuario ni cambia a modo manual. La aceptación no garantiza entrega. No hay deduplicación: repetir una solicitud puede enviar otro mensaje; no reintentes automáticamente un error de resultado incierto.



## OpenAPI

````yaml /openapi.json post /whatsapp/public/v1/templates/send
openapi: 3.1.0
info:
  title: Revem API
  version: 1.0.0
  description: >-
    La API pública de Revem para integraciones de servidor a servidor:
    contactos, organizaciones, tickets, reuniones y el canal de webchat. Se
    autentica con la API key de tu organización.
  contact:
    name: Soporte Revem
    email: soporte@revem.ai
    url: https://revem.ai
servers:
  - url: https://api.revem.ai
    description: Producción
security:
  - apiKey: []
tags:
  - name: WhatsApp
    description: >-
      Envía plantillas aprobadas desde los números conectados de tu
      organización.
  - name: Organizaciones
    description: >-
      Sincroniza empresas por identificador tributario, con atributos
      personalizados por nombre.
  - name: Contactos
    description: >-
      Sincroniza tu base de clientes con Revem. Los contactos se identifican por
      teléfono al crearlos y por id después.
  - name: Tickets
    description: Lee y actualiza los tickets de tu embudo desde tu sistema de gestión.
  - name: Webchat
    description: >-
      Conecta el chat de tu sitio con Revem: registra lo que escribe el
      visitante y lee las respuestas del equipo o del agente.
  - name: Reuniones
    description: >-
      Requiere el módulo meetings. Reuniones independientes de las citas
      médicas, con responsable, capacidad y reservas por contacto y ocurrencia.
paths:
  /whatsapp/public/v1/templates/send:
    post:
      tags:
        - WhatsApp
      summary: Enviar una plantilla de WhatsApp
      description: >-
        Envía una plantilla aprobada desde un número de tu organización. Dentro
        de las 24 horas desde el último mensaje entrante, las plantillas de
        texto sin botones ni cabeceras multimedia se envían como mensajes de
        texto libre; en los demás casos se envían como plantilla. Registra el
        mensaje en la conversación y aplica la política de tickets del canal. No
        asigna el ticket a un usuario ni cambia a modo manual. La aceptación no
        garantiza entrega. No hay deduplicación: repetir una solicitud puede
        enviar otro mensaje; no reintentes automáticamente un error de resultado
        incierto.
      operationId: sendWhatsAppTemplate
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WhatsAppTemplateBody'
            example:
              sender:
                phoneNumber: '+56912345678'
              to: '+56987654321'
              templateName: confirmacion_pedido
              languageCode: es
              variables:
                body:
                  nombre: Ana
                  pedido: '1234'
      responses:
        '200':
          description: Mensaje aceptado y registrado; IDs de conversación y ticket.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateSent'
        '202':
          description: >-
            Meta aceptó el mensaje pero falló el procesamiento local. Conserva
            messageId; no vuelvas a enviar. warning=send_accepted_incomplete.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateAccepted'
        '400':
          description: >-
            Cuerpo, variables o tipo de plantilla inválidos; plantilla no
            aprobada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateError'
        '401':
          description: Sin credencial, o la API key no existe o fue revocada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              example:
                error: Unauthorized
                message: Invalid API key
        '403':
          description: >-
            La credencial no puede usar esta ruta. Una API key sólo alcanza los
            endpoints documentados aquí; cualquier otra ruta de la API responde
            este código.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthError'
              example:
                ok: false
                error: Forbidden
                message: This endpoint is not available to API keys
        '404':
          description: >-
            Remitente no encontrado en tu organización o plantilla/idioma no
            encontrado en su cuenta.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateError'
        '409':
          description: El teléfono coincide con varios remitentes; usa phoneNumberId.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateError'
        '422':
          description: >-
            send_rejected: Meta rechazó explícitamente la solicitud. Corrige la
            causa antes de reintentar.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateError'
        '429':
          description: >-
            La key superó su límite de solicitudes por minuto. El header
            `retry-after` indica cuánto esperar.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'
              example:
                ok: false
                error: Too many requests. Retry in 1 minute.
          headers:
            retry-after:
              description: Segundos que esperar antes de reintentar.
              schema:
                type: integer
            x-ratelimit-limit:
              description: Solicitudes permitidas por minuto.
              schema:
                type: integer
            x-ratelimit-remaining:
              description: Solicitudes que quedan en la ventana actual.
              schema:
                type: integer
            x-ratelimit-reset:
              description: Segundos hasta que la ventana se reinicia.
              schema:
                type: integer
        '502':
          description: >-
            send_uncertain: no se puede confirmar si Meta aceptó el envío. No
            reintentes automáticamente; la ausencia en el historial no demuestra
            que no se envió.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateError'
        '503':
          description: >-
            send_not_sent: falló la preparación antes de iniciar el envío.
            Puedes reintentar con espera tras resolver la causa.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppTemplateError'
components:
  schemas:
    WhatsAppTemplateBody:
      type: object
      properties:
        sender:
          anyOf:
            - type: object
              properties:
                phoneNumberId:
                  type: string
                  maxLength: 32
                  pattern: ^\d+$
              required:
                - phoneNumberId
              additionalProperties: false
            - type: object
              properties:
                phoneNumber:
                  type: string
                  pattern: ^\+?[1-9]\d{6,14}$
              required:
                - phoneNumber
              additionalProperties: false
          description: >-
            Exactamente uno: phoneNumberId (ID de Meta) o phoneNumber (teléfono
            internacional con código de país, sin espacios). Debe pertenecer a
            tu organización.
        to:
          type: string
          pattern: ^\+?[1-9]\d{6,14}$
          description: >-
            Teléfono del destinatario con código de país, sin espacios. El + es
            opcional.
        templateName:
          type: string
          maxLength: 512
          pattern: ^[a-z0-9_]+$
          description: Nombre exacto de la plantilla aprobada en la cuenta del remitente.
        languageCode:
          type: string
          pattern: ^[a-z]{2,3}(?:_[A-Z]{2})?$
          description: Idioma exacto de la plantilla, por ejemplo es o es_CL.
        variables:
          type: object
          properties:
            header:
              type: object
              additionalProperties:
                type: string
                minLength: 1
                maxLength: 4096
            body:
              type: object
              additionalProperties:
                type: string
                minLength: 1
                maxLength: 4096
            buttons:
              type: object
              additionalProperties:
                type: string
                minLength: 1
                maxLength: 2048
          additionalProperties: false
          description: >-
            Mapas de claves y valores de texto, separados en header y body. Usa
            nombres sin llaves (nombre) o posiciones (1, 2). buttons usa el
            índice del botón desde cero y el sufijo de su URL dinámica. No se
            aceptan claves faltantes ni desconocidas.
        mediaId:
          type: string
          format: uuid
          description: >-
            ID de una imagen previamente guardada en Revem para esta plantilla.
            Obligatorio sólo para cabeceras IMAGE. Cabeceras de video/documento
            y botones especiales no se admiten.
        contactName:
          type: string
          minLength: 1
          maxLength: 200
          description: Nombre utilizado al resolver el contacto destinatario.
      required:
        - sender
        - to
        - templateName
        - languageCode
      additionalProperties: false
    WhatsAppTemplateSent:
      type: object
      properties:
        ok:
          type: boolean
          const: true
        conversationId:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
        ticketId:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
      required:
        - ok
        - conversationId
        - ticketId
      additionalProperties: false
    WhatsAppTemplateAccepted:
      type: object
      properties:
        ok:
          type: boolean
          const: true
        conversationId:
          type: 'null'
          description: null porque no se pudo completar el resultado local.
        ticketId:
          type: 'null'
          description: null porque no se pudo completar el resultado local.
        messageId:
          type: string
          description: >-
            ID de Meta (wamid) que confirma la aceptación. No reenvíes esta
            solicitud.
        warning:
          type: string
          const: send_accepted_incomplete
          description: >-
            send_accepted_incomplete: Meta aceptó el mensaje, pero falló el
            registro local o la resolución del ticket. El mensaje puede faltar
            en el historial; requiere revisión operativa, no un nuevo envío.
      required:
        - ok
        - conversationId
        - ticketId
        - messageId
        - warning
      additionalProperties: false
    WhatsAppTemplateError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: string
          description: >-
            Código estable: sender_not_found (404), template_not_found (404),
            ambiguous_sender (409), invalid_template (400), send_rejected (422),
            send_uncertain (502), send_not_sent (503). Los errores globales de
            autenticación, validación y límite de solicitudes pueden contener un
            mensaje en este campo.
        message:
          type: string
          description: >-
            Detalle legible. send_not_sent confirma que no se inició el envío y
            permite reintentar tras resolver la causa. send_rejected requiere
            corregir el rechazo antes de reintentar. send_uncertain no permite
            inferir si Meta aceptó el mensaje: no reintentes automáticamente,
            aunque no aparezca en el historial.
      required:
        - error
      additionalProperties: false
    AuthError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
          description: Presente sólo en el `403`.
        error:
          type: string
        message:
          type: string
      required:
        - error
        - message
    RateLimitError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: string
          description: Incluye cuánto esperar antes de reintentar.
      required:
        - ok
        - error
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: >-
        La API key de tu organización, con la forma `rvm_<prefijo>.<secreto>`,
        enviada como `Authorization: Bearer rvm_…`. Revem la emite y sólo se
        muestra una vez; si la pierdes se reemplaza, no se recupera.

````

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