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

# Enviar quick reply (multi-message)

> Envía un **quick reply** configurado en el business. Un QR puede contener múltiples acciones (text, files, audio, buttons) y cada una emite un mensaje independiente a Meta — por eso la respuesta es un **array** con los mensajes que se generaron en orden.

**Referencia al quick reply — dos formas (provee exactamente una):**

- `quick_reply_uuid`: el UUID canónico. Obtén el catálogo desde `GET /quick-replies`.
- `quick_reply: { name }`: identificación por el string que el agente ve en el dashboard. Único por business case-insensitive ignorando espacios en extremos (`UNIQUE (business_id, LOWER(TRIM(name)))`). El match es **case-insensitive** ("prueba" resuelve "Prueba"). `QUICK_REPLY_AMBIGUOUS` queda como defense-in-depth si un hotfix afloja el unique index.

**Partial success:**

Si alguna de las acciones del QR falla (por ejemplo, Meta rechaza uno de los adjuntos), las otras aún se intentan. La respuesta incluye solo los mensajes que se enviaron con éxito. Si ninguno se envía, la respuesta es `SEND_FAILED` (502). Los mensajes fallidos quedan en `audit_integration_logs` + broadcast de realtime con `status=failed`.

**Guards aplicados:**

- Ventana 24h — **obligatoria**. Si está cerrada, usa `/conversation/messages/template` primero para reabrirla.
- Wallet general — NO aplica (paridad con el envío manual del dashboard).
- Wallet visión — aplica si el QR incluye una acción `files` o `audio` (el AI podría necesitarla al procesar respuestas del cliente).



## OpenAPI

````yaml /openapi.json post /{slug}/conversation/messages/quick-reply
openapi: 3.1.0
info:
  title: 1TO1 AI Public API
  version: 0.2.0
  description: >-
    API pública de 1TO1 AI para integraciones externas (n8n, CRMs, scripts).
    Auth via Bearer token. Rate limit 60 req/min por API key. Contrato REST
    puro: el body de éxito es el payload directo (status HTTP como señal),
    errores retornan `{code, message}` con ambos campos garantizados. Ver schema
    `PublicError`.
servers:
  - url: https://app.1to1.ai/api/v1/public
    description: Producción
security:
  - bearerAuth: []
paths:
  /{slug}/conversation/messages/quick-reply:
    post:
      tags:
        - Messages
      summary: Enviar quick reply (multi-message)
      description: >-
        Envía un **quick reply** configurado en el business. Un QR puede
        contener múltiples acciones (text, files, audio, buttons) y cada una
        emite un mensaje independiente a Meta — por eso la respuesta es un
        **array** con los mensajes que se generaron en orden.


        **Referencia al quick reply — dos formas (provee exactamente una):**


        - `quick_reply_uuid`: el UUID canónico. Obtén el catálogo desde `GET
        /quick-replies`.

        - `quick_reply: { name }`: identificación por el string que el agente ve
        en el dashboard. Único por business case-insensitive ignorando espacios
        en extremos (`UNIQUE (business_id, LOWER(TRIM(name)))`). El match es
        **case-insensitive** ("prueba" resuelve "Prueba").
        `QUICK_REPLY_AMBIGUOUS` queda como defense-in-depth si un hotfix afloja
        el unique index.


        **Partial success:**


        Si alguna de las acciones del QR falla (por ejemplo, Meta rechaza uno de
        los adjuntos), las otras aún se intentan. La respuesta incluye solo los
        mensajes que se enviaron con éxito. Si ninguno se envía, la respuesta es
        `SEND_FAILED` (502). Los mensajes fallidos quedan en
        `audit_integration_logs` + broadcast de realtime con `status=failed`.


        **Guards aplicados:**


        - Ventana 24h — **obligatoria**. Si está cerrada, usa
        `/conversation/messages/template` primero para reabrirla.

        - Wallet general — NO aplica (paridad con el envío manual del
        dashboard).

        - Wallet visión — aplica si el QR incluye una acción `files` o `audio`
        (el AI podría necesitarla al procesar respuestas del cliente).
      parameters:
        - $ref: '#/components/parameters/SlugPathParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendQuickReplyBody'
            examples:
              byUuid:
                summary: Por UUID del QR
                value:
                  conversation:
                    phone: '+525512345678'
                  quick_reply_uuid: 1a2b3c4d-5e6f-7890-1234-567890abcdef
              byName:
                summary: Por nombre
                value:
                  conversation:
                    phone: '+525512345678'
                  quick_reply:
                    name: Bienvenida
      responses:
        '201':
          description: >-
            QR enviado. `messages[]` incluye uno o más mensajes según las
            acciones del QR.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendQuickReplyResponse'
        '400':
          description: >-
            Body inválido (INVALID_REQUEST); o el QR existe pero está vacío
            (QUICK_REPLY_EMPTY — `actions: []` en su configuración).
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '401':
          description: Token ausente, mal formado o no válido (INVALID_API_TOKEN)
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '402':
          description: >-
            Wallet de visión bloqueado (VISION_WALLET_BLOCKED). Solo si el QR
            incluye multimedia.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '403':
          description: >-
            El slug del path no coincide con el business del token
            (TOKEN_BUSINESS_MISMATCH)
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '404':
          description: >-
            Conversación no resuelve (CONVERSATION_NOT_FOUND) / contacto
            asociado no encontrado (CONTACT_NOT_FOUND, race entre el resolve y
            la fase) / quick reply no existe (QUICK_REPLY_NOT_FOUND).
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '409':
          description: >-
            Match por `name` resolvió múltiples QRs (QUICK_REPLY_AMBIGUOUS —
            defense-in-depth, no esperado tras P10a por el unique constraint).
            Pasar `quick_reply_uuid` para desempatar. Además, el identificador
            de conversación puede resultar ambiguo: varios contactos comparten
            el teléfono (`PHONE_NUMBER_AMBIGUOUS`) o el username
            (`USERNAME_AMBIGUOUS`); identifica la conversación por
            `whatsapp_user_id` o `uuid`.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '422':
          description: >-
            Estado que no admite envío: `WINDOW_CLOSED` cuando la ventana de 24h
            ya cerró (envía un template primero para reabrirla). Las
            conversaciones del módulo tester (ficticias) SÍ son aceptadas —
            replican el flujo real sin enviar a Meta, persisten con
            `is_tester=true` y emiten broadcasts al canal tester.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '429':
          description: >-
            Rate limit excedido (RATE_LIMIT_EXCEEDED). Headers `Retry-After`,
            `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`
            indican cuándo reintentar.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '500':
          description: Error inesperado del servidor (UNKNOWN_ERROR)
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
        '502':
          description: >-
            Ninguna acción del QR se envió con éxito (SEND_FAILED). Los fallos
            parciales quedan en audit/realtime.
          headers:
            X-Request-Id:
              schema:
                type: string
                format: uuid
                description: >-
                  ID único para correlacionar con logs server-side. Si el
                  cliente envía uno válido (UUID), se preserva; si no, se genera
                  uno nuevo.
              required: true
              description: >-
                ID único para correlacionar con logs server-side. Si el cliente
                envía uno válido (UUID), se preserva; si no, se genera uno
                nuevo.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicError'
components:
  parameters:
    SlugPathParam:
      schema:
        $ref: '#/components/schemas/SlugPathParam'
      required: true
      description: >-
        Slug del business, case-insensitive. Debe coincidir con el business del
        token.
      name: slug
      in: path
  schemas:
    SendQuickReplyBody:
      allOf:
        - type: object
          properties:
            conversation:
              $ref: '#/components/schemas/ConversationRef'
          required:
            - conversation
        - oneOf:
            - type: object
              properties:
                quick_reply_uuid:
                  type: string
                  format: uuid
                  description: >-
                    UUID del quick reply configurado en el business. Se resuelve
                    contra `quick_replies` con tenant-scope del token.
              required:
                - quick_reply_uuid
            - type: object
              properties:
                quick_reply:
                  $ref: '#/components/schemas/QuickReplyRef'
              required:
                - quick_reply
    SendQuickReplyResponse:
      type: object
      properties:
        messages:
          type: array
          items:
            $ref: '#/components/schemas/QuickReplyMessageItem'
          description: >-
            Array de mensajes emitidos por el QR (en orden). Un QR con 1 sola
            acción produce 1 item; con múltiples acciones (text + files +
            buttons) produce N items.
      required:
        - messages
    PublicError:
      type: object
      properties:
        code:
          type: string
          example: INVALID_API_TOKEN
        message:
          type: string
          example: >-
            The provided API token is invalid or has been revoked. Generate a
            new one in Settings → API Token.
      required:
        - code
        - message
      description: >-
        Public API error body. The client should match against `code` (stable
        canonical identifier) and NOT against `message` (human text, may be
        refined between API versions without notice). The HTTP status code is
        the error-type signal (4xx client, 5xx server).
    SlugPathParam:
      type: string
      example: acme
      description: >-
        Slug del business, case-insensitive. Debe coincidir con el business del
        token.
    ConversationRef:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: >-
            UUID interno de 1TO1 AI. Fallback — los CRMs externos normalmente no
            lo conocen.
        whatsapp_user_id:
          type: string
          description: >-
            BSUID de WhatsApp (identidad opaca de Meta). Se resuelve por
            igualdad exacta contra el identificador BSUID del contacto (no se
            normaliza).
        username:
          type: string
          example: '@mariana.lopez'
          description: >-
            Username público de WhatsApp del contacto. Se acepta con o sin `@`
            inicial y sin distinguir mayúsculas (match case-insensitive contra
            el último username observado por la plataforma; best-effort: el
            usuario puede cambiarlo — la clave estable es `uuid`). Si varios
            contactos lo comparten, la API responde 409 `USERNAME_AMBIGUOUS`.
        phone:
          type: string
          example: +52 55 1234 5678
          description: >-
            Teléfono en formato E.164. Se normaliza (solo dígitos) antes del
            lookup por teléfono del contacto. Puede estar duplicado entre
            contactos (números reciclados / identidades separadas): en ese caso
            la API responde 409 `PHONE_NUMBER_AMBIGUOUS` en vez de adivinar.
      description: >-
        Identificador de la conversación — exactamente UNO de los cuatro campos
        debe venir. Orden de resolución: uuid > whatsapp_user_id > username >
        phone. El lookup filtra por el business del token (defense in depth
        cross-tenant). Resolver por `phone` o `username` puede devolver 409
        (`PHONE_NUMBER_AMBIGUOUS` / `USERNAME_AMBIGUOUS`) cuando varios
        contactos comparten el identificador — aplica a cualquier endpoint que
        acepte esta referencia.
    QuickReplyRef:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
          example: Bienvenida
          description: >-
            Nombre del quick reply. Único por business case-insensitive
            ignorando espacios en extremos (`quick_replies` con UNIQUE en
            `(business_id, LOWER(TRIM(name)))`).
      required:
        - name
      description: >-
        Identificación por `name`. Alternativa a `quick_reply_uuid` — provee
        exactamente UNO de los dos.
    QuickReplyMessageItem:
      type: object
      properties:
        message_uuid:
          type: string
          format: uuid
        wamid:
          type: string
          description: >-
            ID del mensaje asignado por Meta (wa-message-id) por cada
            sub-mensaje del QR. Garantizado non-empty en envíos reales (si Meta
            responde sin wamid, el endpoint devuelve 502 SEND_FAILED). En
            conversaciones tester retorna `""` por diseño.
        subtype:
          type: string
          enum:
            - text
            - image
            - video
            - audio
            - file
            - interactive
          description: >-
            Subtipo del mensaje emitido. Un QR con acciones múltiples genera
            items de subtypes distintos.
      required:
        - message_uuid
        - wamid
        - subtype
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: sk_1to1_<hex>
      description: >-
        API token emitido desde Settings → API Token del dashboard 1TO1 AI.
        Enviar en header Authorization: Bearer sk_1to1_...

````