{
  "openapi": "3.1.0",
  "info": {
    "title": "API Unred — WhatsApp oficial",
    "version": "1.0.0",
    "description": "Conecte o seu sistema (ERP, CRM, loja) ao WhatsApp pela **API oficial da Meta**, através da Unred.\n\n- Base: `https://api.unred.com.br/v1`\n- Autenticação: `Authorization: Bearer unr_live_…` (crie a chave no Unred, em Configurações › Conexão com seu sistema).\n- Chave `unr_test_…`: mesmas respostas e webhooks (`livemode: false`), sem enviar nada.\n- Limite: 600 chamadas por minuto por chave (cabeçalhos `RateLimit-*`).\n- `Idempotency-Key` em todo POST: repetir a chamada nunca envia em dobro.\n- Todo erro: `{ error: { code, message, details, request_id } }`."
  },
  "servers": [
    {
      "url": "https://api.unred.com.br/v1"
    },
    {
      "url": "https://unred.com.br/api/v1",
      "description": "Mesmo serviço, pelo domínio principal"
    }
  ],
  "security": [
    {
      "chave": []
    }
  ],
  "components": {
    "securitySchemes": {
      "chave": {
        "type": "http",
        "scheme": "bearer",
        "description": "`Authorization: Bearer unr_live_…` (ou `unr_test_…`, que não envia nada)."
      }
    },
    "schemas": {
      "Mensagem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "message"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "channel_id": {
            "type": "string"
          },
          "contact": {
            "type": "object",
            "properties": {
              "phone": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "phone",
              "name"
            ]
          },
          "type": {
            "type": "string",
            "description": "text, image, audio, video, document, sticker, location, contact, template, system"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "sent",
              "delivered",
              "read",
              "failed",
              "received"
            ]
          },
          "text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Texto (ou legenda / resumo legível para localização, contato e template)."
          },
          "media": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "url": {
                "type": "string"
              },
              "mime_type": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "file_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "size_bytes": {
                "type": [
                  "number",
                  "null"
                ]
              }
            },
            "required": [
              "url",
              "mime_type",
              "file_name",
              "size_bytes"
            ],
            "description": "Arquivo com link PERMANENTE (o link da Meta vence em 5 minutos; este não)."
          },
          "reply_to": {
            "type": [
              "string",
              "null"
            ]
          },
          "button_reply_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Id/payload do botão ou item de lista que a pessoa tocou."
          },
          "client_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "crm",
              "ai",
              "whatsapp"
            ]
          },
          "wamid": {
            "type": [
              "string",
              "null"
            ]
          },
          "pricing": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "category": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "billable": {
                "type": [
                  "boolean",
                  "null"
                ]
              }
            },
            "required": [
              "category",
              "billable"
            ],
            "description": "Como a Meta cobra esta mensagem (informado por ela no status)."
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "read_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "meta": {
            "description": "Mensagens recebidas: o objeto ORIGINAL da Meta, completo."
          }
        },
        "required": [
          "id",
          "object",
          "direction",
          "channel_id",
          "contact",
          "type",
          "status",
          "text",
          "media",
          "reply_to",
          "button_reply_id",
          "client_reference",
          "source",
          "wamid",
          "pricing",
          "error",
          "created_at",
          "sent_at",
          "delivered_at",
          "read_at"
        ]
      },
      "Erro": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "unauthorized",
                  "account_suspended",
                  "forbidden",
                  "not_found",
                  "conflict",
                  "idempotency_conflict",
                  "channel_not_connected",
                  "channel_ambiguous",
                  "outside_customer_service_window",
                  "recipient_opted_out",
                  "rate_limited",
                  "meta_error",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "code": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        }
                      ]
                    }
                  },
                  "required": [
                    "message"
                  ]
                }
              },
              "request_id": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message",
              "request_id"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "EnviarMensagem": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "description": "Telefone com DDI (E.164). Aceita `+55 11 99999-0000` ou `5511999990000`.",
            "example": "5511999990000"
          },
          "channel_id": {
            "type": "string",
            "description": "Número de origem. Obrigatório só se a conta tiver mais de um."
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "image",
              "audio",
              "video",
              "document",
              "sticker",
              "location",
              "contacts",
              "interactive",
              "template",
              "reaction"
            ],
            "description": "Tipo da mensagem. O objeto de mesmo nome precisa vir junto (ex.: `type: \"text\"` + `text: {...}`)."
          },
          "text": {
            "type": "object",
            "properties": {
              "body": {
                "type": "string",
                "minLength": 1,
                "maxLength": 4096
              },
              "preview_url": {
                "type": "boolean",
                "description": "Mostra a prévia do primeiro link."
              }
            },
            "required": [
              "body"
            ]
          },
          "image": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri",
                "description": "URL pública HTTPS do arquivo (a sua, ou a devolvida por `POST /v1/media`)."
              },
              "id": {
                "type": "string",
                "description": "Id de mídia já enviada à Meta (alternativa ao `link`)."
              },
              "caption": {
                "type": "string",
                "maxLength": 1024,
                "description": "Legenda (imagem, vídeo e documento)."
              },
              "filename": {
                "type": "string",
                "maxLength": 240,
                "description": "Nome do arquivo (documento)."
              }
            },
            "description": "JPEG ou PNG, até 5 MB."
          },
          "audio": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri",
                "description": "URL pública HTTPS do arquivo (a sua, ou a devolvida por `POST /v1/media`)."
              },
              "id": {
                "type": "string",
                "description": "Id de mídia já enviada à Meta (alternativa ao `link`)."
              },
              "caption": {
                "type": "string",
                "maxLength": 1024,
                "description": "Legenda (imagem, vídeo e documento)."
              },
              "filename": {
                "type": "string",
                "maxLength": 240,
                "description": "Nome do arquivo (documento)."
              }
            },
            "description": "AAC, AMR, MP3, M4A ou OGG/Opus, até 16 MB. `voice: true` = mensagem de voz."
          },
          "video": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri",
                "description": "URL pública HTTPS do arquivo (a sua, ou a devolvida por `POST /v1/media`)."
              },
              "id": {
                "type": "string",
                "description": "Id de mídia já enviada à Meta (alternativa ao `link`)."
              },
              "caption": {
                "type": "string",
                "maxLength": 1024,
                "description": "Legenda (imagem, vídeo e documento)."
              },
              "filename": {
                "type": "string",
                "maxLength": 240,
                "description": "Nome do arquivo (documento)."
              }
            },
            "description": "MP4 ou 3GP (H.264 + AAC), até 16 MB."
          },
          "document": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri",
                "description": "URL pública HTTPS do arquivo (a sua, ou a devolvida por `POST /v1/media`)."
              },
              "id": {
                "type": "string",
                "description": "Id de mídia já enviada à Meta (alternativa ao `link`)."
              },
              "caption": {
                "type": "string",
                "maxLength": 1024,
                "description": "Legenda (imagem, vídeo e documento)."
              },
              "filename": {
                "type": "string",
                "maxLength": 240,
                "description": "Nome do arquivo (documento)."
              }
            },
            "description": "PDF, DOC(X), XLS(X), PPT(X), TXT, até 100 MB."
          },
          "sticker": {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "maxLength": 2048,
                "format": "uri",
                "description": "URL pública HTTPS do arquivo (a sua, ou a devolvida por `POST /v1/media`)."
              },
              "id": {
                "type": "string",
                "description": "Id de mídia já enviada à Meta (alternativa ao `link`)."
              },
              "caption": {
                "type": "string",
                "maxLength": 1024,
                "description": "Legenda (imagem, vídeo e documento)."
              },
              "filename": {
                "type": "string",
                "maxLength": 240,
                "description": "Nome do arquivo (documento)."
              }
            },
            "description": "WebP: estático até 100 KB, animado até 500 KB."
          },
          "location": {
            "type": "object",
            "properties": {
              "latitude": {
                "type": "number"
              },
              "longitude": {
                "type": "number"
              },
              "name": {
                "type": "string"
              },
              "address": {
                "type": "string"
              }
            },
            "required": [
              "latitude",
              "longitude"
            ]
          },
          "contacts": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            },
            "minItems": 1,
            "maxItems": 50,
            "description": "Cartões de contato, no formato da Meta (`name`, `phones`, `emails`…)."
          },
          "interactive": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "description": "`button` (até 3 botões), `list`, `cta_url`, `flow`, `product`, `product_list`, `catalog_message`, `location_request_message`…"
              },
              "action": {
                "type": "object",
                "additionalProperties": {}
              }
            },
            "required": [
              "type"
            ]
          },
          "template": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "description": "Nome do template aprovado."
              },
              "language": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "code": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "code"
                    ]
                  }
                ],
                "description": "Código do idioma (`pt_BR`) ou o objeto da Meta (`{ \"code\": \"pt_BR\" }`)."
              },
              "components": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": {}
                },
                "maxItems": 20,
                "description": "Variáveis do cabeçalho, corpo e botões — inclusive carrossel, código de cupom e parâmetros com nome — no formato da Meta."
              }
            },
            "required": [
              "name",
              "language"
            ]
          },
          "reaction": {
            "type": "object",
            "properties": {
              "message_id": {
                "type": "string",
                "description": "Id (nosso ou `wamid`) da mensagem que recebe a reação."
              },
              "emoji": {
                "type": "string",
                "description": "Emoji. Vazio remove a reação."
              }
            },
            "required": [
              "message_id",
              "emoji"
            ]
          },
          "reply_to": {
            "type": "string",
            "description": "Responde citando uma mensagem (id nosso ou `wamid`)."
          },
          "client_reference": {
            "type": "string",
            "maxLength": 512,
            "description": "Seu identificador (pedido, nota…). Volta em todo webhook desta mensagem.",
            "example": "pedido-48213"
          },
          "contact_name": {
            "type": "string",
            "maxLength": 120,
            "description": "Nome da pessoa, usado se ela ainda não existir no Unred."
          }
        },
        "required": [
          "to",
          "type"
        ]
      },
      "ListaDeMensagens": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Mensagem"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ]
      },
      "MarcarLida": {
        "type": "object",
        "properties": {
          "typing_indicator": {
            "type": "boolean",
            "description": "Mostra \"digitando…\" (até 25 s ou até a sua resposta)."
          }
        }
      },
      "Midia": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "media"
            ]
          },
          "url": {
            "type": "string",
            "description": "Link permanente — use em `image.link`, `document.link`…"
          },
          "mime_type": {
            "type": "string"
          },
          "size_bytes": {
            "type": "number"
          },
          "suggested_type": {
            "type": "string"
          },
          "file_name": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "url",
          "mime_type",
          "size_bytes",
          "suggested_type",
          "file_name"
        ]
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ]
          },
          "object": {
            "type": "string",
            "enum": [
              "template"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "APPROVED, PENDING, REJECTED, PAUSED, DISABLED…"
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "sub_category": {
            "type": [
              "string",
              "null"
            ]
          },
          "parameter_format": {
            "type": [
              "string",
              "null"
            ]
          },
          "quality": {
            "type": [
              "string",
              "null"
            ]
          },
          "rejected_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "components": {
            "type": "array",
            "items": {}
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "language",
          "status",
          "category",
          "sub_category",
          "parameter_format",
          "quality",
          "rejected_reason",
          "components"
        ]
      },
      "ListaDeTemplates": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Template"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Passe em `after` pra próxima página."
          }
        },
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor"
        ]
      },
      "CriarTemplate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[a-z0-9_]{1,512}$"
          },
          "language": {
            "type": "string",
            "example": "pt_BR"
          },
          "category": {
            "type": "string",
            "enum": [
              "MARKETING",
              "UTILITY",
              "AUTHENTICATION"
            ]
          },
          "components": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            },
            "minItems": 1,
            "maxItems": 20,
            "description": "Componentes no formato da Meta (HEADER, BODY, FOOTER, BUTTONS, CAROUSEL…)."
          },
          "channel_id": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "language",
          "category",
          "components"
        ]
      },
      "TemplatesPorNome": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Template"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ]
      },
      "Canal": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "channel"
            ]
          },
          "status": {
            "type": "string",
            "description": "connected, disconnected…"
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "display_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "name_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "quality": {
            "type": [
              "string",
              "null"
            ],
            "description": "GREEN, YELLOW, RED"
          },
          "throughput": {
            "type": [
              "string",
              "null"
            ]
          },
          "messaging_limit": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pessoas por 24h fora da janela (nível da conta na Meta)."
          },
          "official_business_account": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "waba_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone_number_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "phone",
          "display_name",
          "name_status",
          "quality",
          "throughput",
          "messaging_limit",
          "official_business_account",
          "waba_id",
          "phone_number_id"
        ]
      },
      "ListaDeCanais": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Canal"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "webhook"
            ]
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "enabled": {
            "type": "boolean"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string"
          },
          "secret": {
            "type": "string",
            "description": "Aparece SÓ na criação e na troca de segredo. Guarde."
          }
        },
        "required": [
          "id",
          "object",
          "url",
          "events",
          "enabled",
          "description",
          "created_at"
        ]
      },
      "ListaDeWebhooks": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "has_more": {
            "type": "boolean"
          }
        },
        "required": [
          "object",
          "data",
          "has_more"
        ]
      },
      "CriarWebhook": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048,
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.reaction",
                "message.edited",
                "message.deleted",
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed",
                "template.status_updated",
                "template.category_updated",
                "template.quality_updated",
                "template.components_updated",
                "channel.updated",
                "contact.marketing_preference_updated",
                "*"
              ]
            },
            "minItems": 1,
            "maxItems": 30,
            "description": "Eventos assinados. `*` = todos."
          },
          "description": {
            "type": "string",
            "maxLength": 200
          }
        },
        "required": [
          "url",
          "events"
        ]
      },
      "AtualizarWebhook": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048,
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "message.received",
                "message.reaction",
                "message.edited",
                "message.deleted",
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed",
                "template.status_updated",
                "template.category_updated",
                "template.quality_updated",
                "template.components_updated",
                "channel.updated",
                "contact.marketing_preference_updated",
                "*"
              ]
            },
            "minItems": 1,
            "maxItems": 30
          },
          "enabled": {
            "type": "boolean"
          },
          "description": {
            "type": "string",
            "maxLength": 200
          }
        }
      },
      "Descadastro": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string",
            "description": "Telefone com DDI (E.164). Aceita `+55 11 99999-0000` ou `5511999990000`.",
            "example": "5511999990000"
          }
        },
        "required": [
          "phone"
        ]
      },
      "Uso": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "usage"
            ]
          },
          "month": {
            "type": "string"
          },
          "franchise": {
            "type": "number",
            "description": "Envios inclusos no plano."
          },
          "counted": {
            "type": "number",
            "description": "Envios pela API aceitos pela Meta no mês (falhas não contam)."
          },
          "remaining": {
            "type": "number"
          },
          "over_franchise": {
            "type": "number"
          },
          "sent": {
            "type": "object",
            "properties": {
              "total": {
                "type": "number"
              },
              "queued": {
                "type": "number"
              },
              "sent": {
                "type": "number"
              },
              "delivered": {
                "type": "number"
              },
              "read": {
                "type": "number"
              },
              "failed": {
                "type": "number"
              }
            },
            "required": [
              "total",
              "queued",
              "sent",
              "delivered",
              "read",
              "failed"
            ]
          },
          "received": {
            "type": "number"
          },
          "meta_billable_by_category": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Envios que a Meta cobra, por categoria (marketing, utility…)."
          },
          "meta_free_by_category": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            }
          },
          "by_day": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string"
                },
                "counted": {
                  "type": "number"
                },
                "failed": {
                  "type": "number"
                }
              },
              "required": [
                "date",
                "counted",
                "failed"
              ]
            }
          },
          "top_errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "message": {
                  "type": "string"
                },
                "count": {
                  "type": "number"
                }
              },
              "required": [
                "code",
                "message",
                "count"
              ]
            }
          }
        },
        "required": [
          "object",
          "month",
          "franchise",
          "counted",
          "remaining",
          "over_franchise",
          "sent",
          "received",
          "meta_billable_by_category",
          "meta_free_by_category",
          "by_day",
          "top_errors"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/messages": {
      "post": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Enviar mensagem",
        "description": "Qualquer tipo que a API oficial do WhatsApp aceita, no MESMO formato da Meta. Responde **202** na hora com o id (`status: queued`); o resultado chega por webhook (`message.sent`, `message.delivered`, `message.read`, `message.failed`). Fora da janela de 24h desde a última mensagem da pessoa, só `template`.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Repetir a chamada com a mesma chave (24h) não executa de novo."
            },
            "required": false,
            "name": "Idempotency-Key",
            "in": "header"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnviarMensagem"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reação enviada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "reaction"
                      ]
                    },
                    "message_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "wamid": {
                      "type": "string"
                    },
                    "emoji": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "message_id",
                    "wamid",
                    "emoji",
                    "status"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Aceita e na fila de envio.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mensagem"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "402": {
            "description": "`account_suspended` — A conta está suspensa (pagamento pendente). Nada é enviado até regularizar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "`channel_not_connected` — O número não está conectado à API oficial agora.\n\n`idempotency_conflict` — A mesma `Idempotency-Key` foi usada com um corpo diferente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "`channel_ambiguous` — A conta tem mais de um número: informe `channel_id`.\n\n`outside_customer_service_window` — Fora da janela de 24h desde a última mensagem da pessoa, a Meta só aceita template. Envie um `template`.\n\n`recipient_opted_out` — A pessoa pediu para não receber marketing. Templates de marketing não são enviados para ela.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Listar mensagens",
        "description": "Enviadas e recebidas, mais novas primeiro. Paginação por `starting_after` (id do último item da página).",
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "starting_after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            },
            "required": false,
            "name": "direction",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "sent",
                "delivered",
                "read",
                "failed",
                "received"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "phone",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "client_reference",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "api"
              ],
              "description": "`api` = só as enviadas pela sua integração."
            },
            "required": false,
            "name": "source",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "ISO-8601"
            },
            "required": false,
            "name": "since",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "ISO-8601"
            },
            "required": false,
            "name": "until",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaDeMensagens"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/messages/{id}": {
      "get": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Consultar mensagem",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Mensagem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/messages/{id}/read": {
      "post": {
        "tags": [
          "Mensagens"
        ],
        "summary": "Marcar recebida como lida",
        "description": "Tique azul pra pessoa; com `typing_indicator: true` mostra \"digitando…\" até a sua resposta.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MarcarLida"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "success"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/media": {
      "post": {
        "tags": [
          "Mídia"
        ],
        "summary": "Subir arquivo",
        "description": "`multipart/form-data`, campo `file`. Devolve um link permanente pra usar em qualquer envio. Imagem até 5 MB, áudio/vídeo até 16 MB, documento até 50 MB.",
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Midia"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/templates": {
      "get": {
        "tags": [
          "Templates"
        ],
        "summary": "Listar templates",
        "description": "Direto da Meta. Paginação por `after` (`next_cursor`).",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "after",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "channel_id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaDeTemplates"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "`channel_ambiguous` — A conta tem mais de um número: informe `channel_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "502": {
            "description": "`meta_error` — A Meta recusou a operação. `details` traz o código e a mensagem dela.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Templates"
        ],
        "summary": "Criar template",
        "description": "Submete pra aprovação da Meta. O resultado chega por `template.status_updated`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CriarTemplate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "object": {
                      "type": "string",
                      "enum": [
                        "template"
                      ]
                    },
                    "name": {},
                    "status": {
                      "type": "string"
                    },
                    "category": {}
                  },
                  "required": [
                    "id",
                    "object",
                    "status"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "502": {
            "description": "`meta_error` — A Meta recusou a operação. `details` traz o código e a mensagem dela.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/templates/{name}": {
      "get": {
        "tags": [
          "Templates"
        ],
        "summary": "Consultar template (todos os idiomas)",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "name",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "channel_id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplatesPorNome"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Templates"
        ],
        "summary": "Apagar template",
        "description": "Apaga em todos os idiomas; com `hsm_id`, só aquele.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "name",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "hsm_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "channel_id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    },
                    "name": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "deleted",
                    "name"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "502": {
            "description": "`meta_error` — A Meta recusou a operação. `details` traz o código e a mensagem dela.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/channels": {
      "get": {
        "tags": [
          "Números"
        ],
        "summary": "Listar números",
        "description": "Qualidade, nome de exibição e limite de envio, ao vivo da Meta.",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaDeCanais"
                }
              }
            }
          }
        }
      }
    },
    "/channels/{id}/profile": {
      "get": {
        "tags": [
          "Números"
        ],
        "summary": "Perfil comercial",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Números"
        ],
        "summary": "Atualizar perfil comercial",
        "description": "Campos da Meta: `about`, `address`, `description`, `email`, `websites`, `vertical`.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "502": {
            "description": "`meta_error` — A Meta recusou a operação. `details` traz o código e a mensagem dela.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Listar webhooks",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListaDeWebhooks"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Criar webhook",
        "description": "Devolve o `secret` (só agora) pra conferir a assinatura `Unred-Signature`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CriarWebhook"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "`conflict` — A operação conflita com o estado atual do recurso.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Consultar webhook",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Alterar webhook",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AtualizarWebhook"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Apagar webhook",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "deleted"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Enviar evento de teste",
        "description": "Manda `webhook.test` agora e devolve o que o seu servidor respondeu.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "response_status": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "response_status"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Trocar o segredo",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Histórico de entregas",
        "description": "Cada evento, tentativas, último status HTTP do seu servidor e próximo reenvio.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer"
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/deliveries/{deliveryId}/retry": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Reenviar uma entrega",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "deliveryId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "delivery_id": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "delivery_id"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/marketing-opt-outs": {
      "get": {
        "tags": [
          "Descadastro"
        ],
        "summary": "Listar descadastrados",
        "description": "Quem não recebe template de MARKETING (utilidade e autenticação continuam).",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Descadastro"
        ],
        "summary": "Descadastrar telefone",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Descadastro"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/marketing-opt-outs/{phone}": {
      "delete": {
        "tags": [
          "Descadastro"
        ],
        "summary": "Recadastrar telefone",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": true,
            "name": "phone",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {}
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — O recurso não existe nesta conta.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "tags": [
          "Uso"
        ],
        "summary": "Uso do mês",
        "description": "Envios contados pra franquia, falhas, recebidas e o que a Meta cobra por categoria. A mesma conta da sua fatura.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "2026-10"
            },
            "required": false,
            "name": "month",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Uso"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    },
    "/usage/messages.csv": {
      "get": {
        "tags": [
          "Uso"
        ],
        "summary": "Planilha das mensagens do mês",
        "description": "Uma linha por mensagem enviada pela API no mês (CSV, UTF-8, separado por vírgula): status, se conta na franquia, categoria e cobrança da Meta, erro. É o comprovante da contagem.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "2026-10"
            },
            "required": false,
            "name": "month",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Arquivo CSV",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — O corpo ou os parâmetros não passaram na validação. `details` diz qual campo.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Chave ausente, inválida ou revogada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden` — A chave não pode fazer esta operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Muitas chamadas em pouco tempo. Respeite o cabeçalho `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "message.received": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.received",
        "description": "A pessoa mandou uma mensagem (texto, mídia, localização, contato, toque em botão, formulário, pedido…). Mídia chega com link permanente.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.reaction": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.reaction",
        "description": "A pessoa reagiu (ou tirou a reação) a uma mensagem. `emoji` vazio = tirou.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.edited": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.edited",
        "description": "A pessoa editou uma mensagem que tinha mandado. `text` é a versão nova.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.deleted": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.deleted",
        "description": "A pessoa apagou uma mensagem para todos.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.sent": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.sent",
        "description": "A Meta aceitou a mensagem e ela saiu.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.delivered": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.delivered",
        "description": "A mensagem chegou no celular da pessoa.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.read": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.read",
        "description": "A pessoa leu (só quando ela deixa a confirmação de leitura ligada).",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "message.failed": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "message.failed",
        "description": "A mensagem não foi entregue. `error.code` traz o código da Meta.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "template.status_updated": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "template.status_updated",
        "description": "Um template foi aprovado, recusado, pausado ou desativado pela Meta.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "template.category_updated": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "template.category_updated",
        "description": "A Meta mudou a categoria de um template — isso muda o preço dele.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "template.quality_updated": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "template.quality_updated",
        "description": "A nota de qualidade de um template mudou.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "template.components_updated": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "template.components_updated",
        "description": "O conteúdo de um template foi alterado.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "channel.updated": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "channel.updated",
        "description": "Mudou algo no número: qualidade, nome de exibição, limite de envio ou alerta da conta.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    },
    "contact.marketing_preference_updated": {
      "post": {
        "tags": [
          "Eventos"
        ],
        "summary": "contact.marketing_preference_updated",
        "description": "A pessoa parou (ou voltou a aceitar) mensagens de marketing pelo próprio WhatsApp.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Responda 2xx em até 10 s. Qualquer outra coisa = reenvio (1 min, 5 min, 25 min, 2 h, 10 h)."
          }
        }
      }
    }
  }
}