{
  "openapi": "3.1.0",
  "info": {
    "title": "API da Torqyn",
    "version": "2026-10-01",
    "description": "A Torqyn como camada de conversa do seu sistema: você manda dados e eventos, nós falamos com a pessoa pelo WhatsApp e pelos outros canais, e devolvemos o que aconteceu por webhook. Guias, segurança e conformidade em https://torqyn.com/docs."
  },
  "x-torqyn": {
    "errors": {
      "invalid_request": {
        "status": 400,
        "title": "Requisição inválida"
      },
      "invalid_version": {
        "status": 400,
        "title": "Versão da API desconhecida"
      },
      "idempotency_key_required": {
        "status": 400,
        "title": "Falta a Idempotency-Key"
      },
      "unauthorized": {
        "status": 401,
        "title": "Chave de API ausente ou inválida"
      },
      "forbidden_scope": {
        "status": 403,
        "title": "A chave não tem o escopo desta rota"
      },
      "not_found": {
        "status": 404,
        "title": "Não encontrado"
      },
      "conflict": {
        "status": 409,
        "title": "Conflito com o estado atual"
      },
      "rejected": {
        "status": 409,
        "title": "Recusado pela regra de negócio"
      },
      "opted_out": {
        "status": 409,
        "title": "A pessoa pediu para não receber mensagem"
      },
      "idempotency_key_in_use": {
        "status": 409,
        "title": "Outra requisição com esta Idempotency-Key ainda está rodando"
      },
      "payload_too_large": {
        "status": 413,
        "title": "Corpo maior que o permitido"
      },
      "unsupported_media_type": {
        "status": 415,
        "title": "Envie o corpo como application/json"
      },
      "idempotency_key_reused": {
        "status": 422,
        "title": "Idempotency-Key já usada com outro corpo ou em outra rota"
      },
      "rate_limited": {
        "status": 429,
        "title": "Limite de requisições atingido"
      },
      "internal_error": {
        "status": 500,
        "title": "Erro interno"
      }
    },
    "scopes": {
      "contacts:read": "Ler contatos",
      "contacts:write": "Criar e atualizar contatos",
      "consents:write": "Registrar e revogar consentimentos",
      "events:read": "Ler os tipos de evento e os eventos enviados",
      "events:write": "Mandar eventos para a Torqyn falar com a pessoa",
      "messages:read": "Ler o status das mensagens e os modelos",
      "messages:write": "Mandar mensagens",
      "conversations:read": "Ler a lista e o estado das conversas, sem o conteúdo",
      "conversations:read_content": "Ler o que foi dito nas conversas (dado pessoal)",
      "webhooks:read": "Ler os endpoints de webhook",
      "webhooks:write": "Criar e mudar endpoints de webhook",
      "payments:write": "Criar cobranças Pix",
      "accounts:write": "Criar contas filhas (parceiro)"
    },
    "versions": [
      "2026-10-01"
    ],
    "limits": {
      "perKeyPerMinute": 120,
      "perAccountPerMinute": 300,
      "authFailuresPerIp": 20,
      "authFailureWindowMinutes": 10,
      "ipBlockMinutes": 15,
      "bodyMegabytes": 1,
      "idempotencyHours": 24,
      "requestLogDays": 30
    },
    "webhooks": {
      "egressIp": "54.94.20.141",
      "timeoutSeconds": 10,
      "retryMinutes": [
        1,
        5,
        30,
        120,
        360,
        720
      ],
      "maxAgeHours": 24,
      "pauseAfterFailures": 20,
      "secretOverlapHours": 24,
      "historyDays": 30,
      "signatureToleranceSeconds": 300
    },
    "sandbox": {
      "replyEveryMinutes": 10,
      "numbers": [
        {
          "phone": "+5511900000001",
          "label": "entrega e lê"
        },
        {
          "phone": "+5511900000002",
          "label": "entrega, lê e responde \"sim\""
        },
        {
          "phone": "+5511900000003",
          "label": "falha: número sem WhatsApp"
        },
        {
          "phone": "+5511900000004",
          "label": "entrega e nunca lê"
        },
        {
          "phone": "+5511900000005",
          "label": "entrega, lê e responde \"SAIR\""
        }
      ]
    }
  },
  "servers": [
    {
      "url": "https://platform.torqyn.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Começar"
    },
    {
      "name": "Contatos"
    },
    {
      "name": "Eventos"
    },
    {
      "name": "Webhooks"
    }
  ],
  "paths": {
    "/v1/ping": {
      "get": {
        "operationId": "ping",
        "summary": "Conferir a chave",
        "description": "Responde com a conta, o modo (teste ou produção) e a versão da API. Serve para conferir a chave e a conexão antes de integrar; não pede escopo.",
        "tags": [
          "Começar"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "ping"
                    },
                    "account": {
                      "type": "string",
                      "description": "Id da conta que a chave abre"
                    },
                    "livemode": {
                      "type": "boolean",
                      "description": "true com chave de produção (tq_live), false com a de teste"
                    },
                    "api_version": {
                      "type": "string",
                      "description": "Versão da API que respondeu"
                    }
                  },
                  "required": [
                    "object",
                    "account",
                    "livemode",
                    "api_version"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "ping",
                  "account": "0f6a3c1e-2b4d-4e8a-9c21-7d4e5f6a8b90",
                  "livemode": false,
                  "api_version": "2026-10-01"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{external_id}": {
      "put": {
        "operationId": "upsertContact",
        "summary": "Criar ou atualizar um contato",
        "description": "Cria o contato pelo id do seu sistema, ou atualiza se ele já existe. Campo omitido fica como está; `null` apaga. O telefone e o e-mail que vêm do seu sistema contam como confirmados, e o contato se liga sozinho à conversa que a mesma pessoa já tem pelo WhatsApp. `tags` (pelo nome, como cadastradas no painel) passa a ser a lista de etiquetas que a API pôs: as que saírem da lista são tiradas; as que o time pôs à mão, nunca.",
        "tags": [
          "Contatos"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "contacts:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:@-]{1,120}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "phone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^\\+[1-9]\\d{7,14}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 160,
                        "format": "email",
                        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "tags": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 2,
                      "maxLength": 40
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "id": {
                      "type": "string",
                      "description": "Id do contato na Torqyn"
                    },
                    "external_id": {
                      "type": "string",
                      "description": "O id do contato no seu sistema"
                    },
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "description": "Telefone em E.164",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "email": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Etiquetas do contato, pelo nome"
                    },
                    "opted_out": {
                      "type": "boolean",
                      "description": "A pessoa pediu para sair: não recebe nenhuma mensagem ativa, em nenhum canal"
                    },
                    "consents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string",
                            "enum": [
                              "whatsapp",
                              "email",
                              "instagram",
                              "messenger",
                              "telegram"
                            ]
                          },
                          "purpose": {
                            "type": "string",
                            "enum": [
                              "marketing",
                              "utility"
                            ]
                          },
                          "origin": {
                            "type": "string"
                          },
                          "granted_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "channel",
                          "purpose",
                          "origin",
                          "granted_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "external_id",
                    "name",
                    "phone",
                    "email",
                    "tags",
                    "opted_out",
                    "consents",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "contact",
                  "id": "6f1c2a90-5b3e-4d7a-9e12-3c4b5a6d7e8f",
                  "external_id": "fam-123",
                  "name": "Ana Martins",
                  "phone": "+5583999998888",
                  "email": "ana@exemplo.com.br",
                  "tags": [
                    "Plano família"
                  ],
                  "opted_out": false,
                  "consents": [
                    {
                      "channel": "whatsapp",
                      "purpose": "utility",
                      "origin": "api",
                      "granted_at": "2026-10-01T12:00:00.000Z"
                    }
                  ],
                  "created_at": "2026-10-01T12:00:00.000Z",
                  "updated_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getContact",
        "summary": "Ler um contato",
        "description": "O contato pelo id do seu sistema, com as etiquetas e os consentimentos em vigor. Documento (CPF/CNPJ) nunca sai pela API.",
        "tags": [
          "Contatos"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "contacts:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:@-]{1,120}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "id": {
                      "type": "string",
                      "description": "Id do contato na Torqyn"
                    },
                    "external_id": {
                      "type": "string",
                      "description": "O id do contato no seu sistema"
                    },
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "description": "Telefone em E.164",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "email": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Etiquetas do contato, pelo nome"
                    },
                    "opted_out": {
                      "type": "boolean",
                      "description": "A pessoa pediu para sair: não recebe nenhuma mensagem ativa, em nenhum canal"
                    },
                    "consents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string",
                            "enum": [
                              "whatsapp",
                              "email",
                              "instagram",
                              "messenger",
                              "telegram"
                            ]
                          },
                          "purpose": {
                            "type": "string",
                            "enum": [
                              "marketing",
                              "utility"
                            ]
                          },
                          "origin": {
                            "type": "string"
                          },
                          "granted_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "channel",
                          "purpose",
                          "origin",
                          "granted_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "external_id",
                    "name",
                    "phone",
                    "email",
                    "tags",
                    "opted_out",
                    "consents",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "contact",
                  "id": "6f1c2a90-5b3e-4d7a-9e12-3c4b5a6d7e8f",
                  "external_id": "fam-123",
                  "name": "Ana Martins",
                  "phone": "+5583999998888",
                  "email": "ana@exemplo.com.br",
                  "tags": [
                    "Plano família"
                  ],
                  "opted_out": false,
                  "consents": [
                    {
                      "channel": "whatsapp",
                      "purpose": "utility",
                      "origin": "api",
                      "granted_at": "2026-10-01T12:00:00.000Z"
                    }
                  ],
                  "created_at": "2026-10-01T12:00:00.000Z",
                  "updated_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{external_id}/consents": {
      "post": {
        "operationId": "grantConsent",
        "summary": "Registrar um consentimento",
        "description": "Registra que a pessoa aceitou receber mensagem num canal e para uma finalidade, com a evidência de como aceitou no seu sistema. `marketing` é o que permite mandar oferta e novidade; `utility` é o serviço de algo que ela já contratou. Quem pediu para sair não recebe consentimento pela API (`opted_out`).",
        "tags": [
          "Contatos"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "consents:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:@-]{1,120}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "whatsapp",
                      "email",
                      "instagram",
                      "messenger",
                      "telegram"
                    ]
                  },
                  "purpose": {
                    "type": "string",
                    "enum": [
                      "marketing",
                      "utility"
                    ]
                  },
                  "evidence": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  }
                },
                "required": [
                  "channel",
                  "purpose",
                  "evidence"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "id": {
                      "type": "string",
                      "description": "Id do contato na Torqyn"
                    },
                    "external_id": {
                      "type": "string",
                      "description": "O id do contato no seu sistema"
                    },
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "description": "Telefone em E.164",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "email": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Etiquetas do contato, pelo nome"
                    },
                    "opted_out": {
                      "type": "boolean",
                      "description": "A pessoa pediu para sair: não recebe nenhuma mensagem ativa, em nenhum canal"
                    },
                    "consents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string",
                            "enum": [
                              "whatsapp",
                              "email",
                              "instagram",
                              "messenger",
                              "telegram"
                            ]
                          },
                          "purpose": {
                            "type": "string",
                            "enum": [
                              "marketing",
                              "utility"
                            ]
                          },
                          "origin": {
                            "type": "string"
                          },
                          "granted_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "channel",
                          "purpose",
                          "origin",
                          "granted_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "external_id",
                    "name",
                    "phone",
                    "email",
                    "tags",
                    "opted_out",
                    "consents",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "contact",
                  "id": "6f1c2a90-5b3e-4d7a-9e12-3c4b5a6d7e8f",
                  "external_id": "fam-123",
                  "name": "Ana Martins",
                  "phone": "+5583999998888",
                  "email": "ana@exemplo.com.br",
                  "tags": [
                    "Plano família"
                  ],
                  "opted_out": false,
                  "consents": [
                    {
                      "channel": "whatsapp",
                      "purpose": "utility",
                      "origin": "api",
                      "granted_at": "2026-10-01T12:00:00.000Z"
                    }
                  ],
                  "created_at": "2026-10-01T12:00:00.000Z",
                  "updated_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`, `idempotency_key_required`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_in_use`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`idempotency_key_reused`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{external_id}/consents/{channel}/{purpose}": {
      "delete": {
        "operationId": "revokeConsent",
        "summary": "Revogar um consentimento",
        "description": "Revoga o consentimento daquele canal e finalidade. O registro não é apagado: fica como prova do período em que valeu.",
        "tags": [
          "Contatos"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "consents:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "external_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:@-]{1,120}$"
            }
          },
          {
            "name": "channel",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "whatsapp",
                "email",
                "instagram",
                "messenger",
                "telegram"
              ]
            }
          },
          {
            "name": "purpose",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "marketing",
                "utility"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "id": {
                      "type": "string",
                      "description": "Id do contato na Torqyn"
                    },
                    "external_id": {
                      "type": "string",
                      "description": "O id do contato no seu sistema"
                    },
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "phone": {
                      "description": "Telefone em E.164",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "email": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Etiquetas do contato, pelo nome"
                    },
                    "opted_out": {
                      "type": "boolean",
                      "description": "A pessoa pediu para sair: não recebe nenhuma mensagem ativa, em nenhum canal"
                    },
                    "consents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "channel": {
                            "type": "string",
                            "enum": [
                              "whatsapp",
                              "email",
                              "instagram",
                              "messenger",
                              "telegram"
                            ]
                          },
                          "purpose": {
                            "type": "string",
                            "enum": [
                              "marketing",
                              "utility"
                            ]
                          },
                          "origin": {
                            "type": "string"
                          },
                          "granted_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "channel",
                          "purpose",
                          "origin",
                          "granted_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "external_id",
                    "name",
                    "phone",
                    "email",
                    "tags",
                    "opted_out",
                    "consents",
                    "created_at",
                    "updated_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "contact",
                  "id": "6f1c2a90-5b3e-4d7a-9e12-3c4b5a6d7e8f",
                  "external_id": "fam-123",
                  "name": "Ana Martins",
                  "phone": "+5583999998888",
                  "email": "ana@exemplo.com.br",
                  "tags": [
                    "Plano família"
                  ],
                  "opted_out": false,
                  "consents": [],
                  "created_at": "2026-10-01T12:00:00.000Z",
                  "updated_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/events": {
      "post": {
        "operationId": "sendEvent",
        "summary": "Mandar um evento",
        "description": "Manda um evento de um tipo cadastrado para um contato. Com a janela de 24 h do WhatsApp aberta e a IA atendendo, a IA escreve seguindo a instrução do tipo; senão sai o modelo aprovado do tipo. O que impede o envio (sem telefone, sem canal, fora da janela sem modelo, modelo não aprovado, sem consentimento de marketing) volta com `status: failed` e o motivo. Quem pediu para sair nunca recebe: a resposta é `opted_out` e nada sai. O mesmo evento duas vezes, com a mesma Idempotency-Key, sai uma vez.",
        "tags": [
          "Eventos"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "events:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 41,
                    "description": "A chave do tipo de evento, como cadastrada"
                  },
                  "contact": {
                    "type": "object",
                    "properties": {
                      "external_id": {
                        "type": "string",
                        "pattern": "^[A-Za-z0-9._:@-]{1,120}$"
                      }
                    },
                    "required": [
                      "external_id"
                    ],
                    "additionalProperties": false
                  },
                  "data": {
                    "default": {},
                    "description": "Os valores das variáveis do tipo; datas em ISO 8601",
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "null"
                      ]
                    }
                  }
                },
                "required": [
                  "type",
                  "contact"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "event"
                    },
                    "type": {
                      "type": "string"
                    },
                    "contact": {
                      "type": "object",
                      "properties": {
                        "external_id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "external_id"
                      ],
                      "additionalProperties": false
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "delivered",
                        "failed",
                        "duplicate"
                      ],
                      "description": "`delivered`: a mensagem saiu. `failed`: não saiu, e `reason` diz por quê. `duplicate`: esta Idempotency-Key já tinha sido usada."
                    },
                    "reason": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "blocked",
                            "no_phone",
                            "no_channel",
                            "outside_window",
                            "handled_by_team",
                            "template_not_approved",
                            "no_consent",
                            "template_params",
                            "delivery_failed",
                            "ai_unavailable",
                            "ai_no_reply"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "detail": {
                      "description": "O motivo em português, para o log do seu sistema",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "via": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "ai",
                            "template"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "`ai`: a IA escreveu, com a janela de 24 h aberta. `template`: saiu o modelo aprovado."
                    },
                    "channel": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "conversation_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "type",
                    "contact",
                    "status",
                    "reason",
                    "detail",
                    "via",
                    "channel",
                    "conversation_id"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "event",
                  "type": "consulta_amanha",
                  "contact": {
                    "external_id": "fam-123"
                  },
                  "status": "delivered",
                  "reason": null,
                  "detail": null,
                  "via": "template",
                  "channel": "whatsapp",
                  "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`, `idempotency_key_required`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_in_use`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`idempotency_key_reused`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listEvents",
        "summary": "Listar os eventos dos últimos 30 dias",
        "description": "Os eventos que saíram (ou sairiam) pelos webhooks nos últimos 30 dias, do mais novo para o mais antigo, no mesmo envelope, sem campo pessoal do contato (só os ids). Serve para conferir o que o seu endpoint perdeu. Filtre por `type`.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "events:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só um tipo de evento",
              "type": "string",
              "enum": [
                "contact.opted_out",
                "message.received",
                "message.sent",
                "message.delivered",
                "message.read",
                "message.failed",
                "conversation.handed_off",
                "appointment.created",
                "payment.succeeded",
                "case.stage_changed",
                "case.won",
                "case.lost",
                "event.delivered",
                "event.failed"
              ]
            },
            "description": "Só um tipo de evento"
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "O id do evento: o mesmo em toda tentativa de entrega"
                          },
                          "type": {
                            "type": "string"
                          },
                          "api_version": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created": {
                            "type": "string"
                          },
                          "livemode": {
                            "type": "boolean"
                          },
                          "account": {
                            "type": "string"
                          },
                          "data": {
                            "type": "object",
                            "properties": {
                              "object": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "required": [
                              "object"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "required": [
                          "id",
                          "type",
                          "api_version",
                          "created",
                          "livemode",
                          "account",
                          "data"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "0f6a3c1e-8b2d-4e5f-9a1b-2c3d4e5f6a7b",
                      "type": "message.delivered",
                      "api_version": "2026-10-01",
                      "created": "2026-10-02T10:15:03.000Z",
                      "livemode": false,
                      "account": "1a2b3c4d-5e6f-4a8b-9c0d-1e2f3a4b5c6d",
                      "data": {
                        "object": {
                          "object": "message",
                          "id": "3a5c7e9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
                          "direction": "outbound",
                          "status": "delivered",
                          "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                          "channel": "whatsapp",
                          "contact": {
                            "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                            "external_id": "fam-123"
                          }
                        }
                      }
                    }
                  ],
                  "has_more": false
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/event-types": {
      "get": {
        "operationId": "listEventTypes",
        "summary": "Listar os tipos de evento",
        "description": "Os tipos de evento cadastrados nesta conta, com as variáveis que cada um espera. Cadastrar e mudar é no painel, em Configurações → Desenvolvedores.",
        "tags": [
          "Eventos"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "events:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "event_type"
                          },
                          "type": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "variables": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "type": {
                                  "type": "string",
                                  "enum": [
                                    "text",
                                    "date",
                                    "number"
                                  ]
                                },
                                "example": {
                                  "type": "string"
                                },
                                "required": {
                                  "type": "boolean"
                                }
                              },
                              "required": [
                                "name",
                                "type",
                                "example",
                                "required"
                              ],
                              "additionalProperties": false
                            }
                          },
                          "speaks_with": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "ai",
                                "template"
                              ]
                            },
                            "description": "Como a Torqyn fala neste tipo: a IA (janela aberta) e/ou o modelo aprovado"
                          }
                        },
                        "required": [
                          "object",
                          "type",
                          "description",
                          "variables",
                          "speaks_with"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "object",
                    "data"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "event_type",
                      "type": "consulta_amanha",
                      "description": "Lembrete da consulta do dia seguinte",
                      "variables": [
                        {
                          "name": "data_consulta",
                          "type": "date",
                          "example": "2026-10-02T15:00:00-03:00",
                          "required": true
                        },
                        {
                          "name": "medico",
                          "type": "text",
                          "example": "Dra. Ana",
                          "required": true
                        }
                      ],
                      "speaks_with": [
                        "ai",
                        "template"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "summary": "Listar os endpoints de webhook",
        "description": "Os endpoints desta conta (a de teste ou a de produção, pela chave), sem o segredo. Inclui os desligados.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "object": {
                            "type": "string",
                            "const": "webhook_endpoint"
                          },
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "events": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "customer_fields": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "api_version": {
                            "description": "A versão do corpo, fixada na criação",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active",
                              "paused",
                              "disabled"
                            ],
                            "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                          },
                          "pause_reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "previous_secret_valid_until": {
                            "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "livemode": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "object",
                          "id",
                          "name",
                          "url",
                          "events",
                          "customer_fields",
                          "api_version",
                          "status",
                          "pause_reason",
                          "previous_secret_valid_until",
                          "livemode",
                          "created_at"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "webhook_endpoint",
                      "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                      "name": "Meu sistema",
                      "url": "https://api.seusistema.com.br/torqyn",
                      "events": [
                        "message.delivered",
                        "message.failed",
                        "appointment.created"
                      ],
                      "customer_fields": [],
                      "api_version": "2026-10-01",
                      "status": "active",
                      "pause_reason": null,
                      "previous_secret_valid_until": null,
                      "livemode": false,
                      "created_at": "2026-10-01T12:00:00.000Z"
                    }
                  ],
                  "has_more": false
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "summary": "Criar um endpoint de webhook",
        "description": "Cria o endpoint e devolve o segredo `whsec_…` **só nesta resposta**: guarde-o para conferir a assinatura (`Torqyn-Signature`). A URL precisa ser https e resolver para um endereço público. A versão do corpo fica presa à versão desta requisição.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80
                  },
                  "url": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 500
                  },
                  "events": {
                    "minItems": 1,
                    "maxItems": 14,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "const": "*"
                        },
                        {
                          "type": "string",
                          "enum": [
                            "contact.opted_out",
                            "message.received",
                            "message.sent",
                            "message.delivered",
                            "message.read",
                            "message.failed",
                            "conversation.handed_off",
                            "appointment.created",
                            "payment.succeeded",
                            "case.stage_changed",
                            "case.won",
                            "case.lost",
                            "event.delivered",
                            "event.failed"
                          ]
                        }
                      ]
                    },
                    "description": "Os eventos que o endpoint recebe, ou `[\"*\"]` para todos (inclusive os que vierem)"
                  },
                  "customer_fields": {
                    "default": [],
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "nome",
                        "telefone",
                        "email"
                      ]
                    },
                    "description": "Campos do contato que vão no corpo: `nome`, `telefone`, `email`. Vazio: só os ids. Documento nunca sai."
                  }
                },
                "required": [
                  "name",
                  "url",
                  "events"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "customer_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "api_version": {
                      "description": "A versão do corpo, fixada na criação",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused",
                        "disabled"
                      ],
                      "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                    },
                    "pause_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "previous_secret_valid_until": {
                      "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string",
                      "description": "O segredo de assinatura. Não aparece de novo."
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "name",
                    "url",
                    "events",
                    "customer_fields",
                    "api_version",
                    "status",
                    "pause_reason",
                    "previous_secret_valid_until",
                    "livemode",
                    "created_at",
                    "secret"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                  "name": "Meu sistema",
                  "url": "https://api.seusistema.com.br/torqyn",
                  "events": [
                    "message.delivered",
                    "message.failed",
                    "appointment.created"
                  ],
                  "customer_fields": [],
                  "api_version": "2026-10-01",
                  "status": "active",
                  "pause_reason": null,
                  "previous_secret_valid_until": null,
                  "livemode": false,
                  "created_at": "2026-10-01T12:00:00.000Z",
                  "secret": "whsec_6q2Jb0xVn3cKp9sT1mRw4yZa7uEo5iLd"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`, `idempotency_key_required`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_in_use`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`idempotency_key_reused`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}": {
      "get": {
        "operationId": "getWebhookEndpoint",
        "summary": "Ler um endpoint de webhook",
        "description": "O endpoint, sem o segredo.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:read",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "customer_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "api_version": {
                      "description": "A versão do corpo, fixada na criação",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused",
                        "disabled"
                      ],
                      "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                    },
                    "pause_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "previous_secret_valid_until": {
                      "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "name",
                    "url",
                    "events",
                    "customer_fields",
                    "api_version",
                    "status",
                    "pause_reason",
                    "previous_secret_valid_until",
                    "livemode",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                  "name": "Meu sistema",
                  "url": "https://api.seusistema.com.br/torqyn",
                  "events": [
                    "message.delivered",
                    "message.failed",
                    "appointment.created"
                  ],
                  "customer_fields": [],
                  "api_version": "2026-10-01",
                  "status": "active",
                  "pause_reason": null,
                  "previous_secret_valid_until": null,
                  "livemode": false,
                  "created_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWebhookEndpoint",
        "summary": "Mudar um endpoint de webhook",
        "description": "Troca nome, URL, eventos ou campos do contato. `enabled: true` religa um endpoint desligado. Para pausar e reativar, use as rotas próprias; para trocar o segredo, `rotate-secret`.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80
                  },
                  "url": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 500
                  },
                  "events": {
                    "minItems": 1,
                    "maxItems": 14,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "const": "*"
                        },
                        {
                          "type": "string",
                          "enum": [
                            "contact.opted_out",
                            "message.received",
                            "message.sent",
                            "message.delivered",
                            "message.read",
                            "message.failed",
                            "conversation.handed_off",
                            "appointment.created",
                            "payment.succeeded",
                            "case.stage_changed",
                            "case.won",
                            "case.lost",
                            "event.delivered",
                            "event.failed"
                          ]
                        }
                      ]
                    },
                    "description": "Os eventos que o endpoint recebe, ou `[\"*\"]` para todos (inclusive os que vierem)"
                  },
                  "customer_fields": {
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "nome",
                        "telefone",
                        "email"
                      ]
                    },
                    "description": "Campos do contato que vão no corpo: `nome`, `telefone`, `email`. Vazio: só os ids. Documento nunca sai."
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "customer_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "api_version": {
                      "description": "A versão do corpo, fixada na criação",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused",
                        "disabled"
                      ],
                      "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                    },
                    "pause_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "previous_secret_valid_until": {
                      "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "name",
                    "url",
                    "events",
                    "customer_fields",
                    "api_version",
                    "status",
                    "pause_reason",
                    "previous_secret_valid_until",
                    "livemode",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                  "name": "Meu sistema",
                  "url": "https://api.seusistema.com.br/torqyn",
                  "events": [
                    "message.delivered",
                    "message.failed",
                    "appointment.created"
                  ],
                  "customer_fields": [],
                  "api_version": "2026-10-01",
                  "status": "active",
                  "pause_reason": null,
                  "previous_secret_valid_until": null,
                  "livemode": false,
                  "created_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "summary": "Desligar um endpoint de webhook",
        "description": "Desliga o endpoint: para de receber eventos, e o histórico de entregas fica. Religue com `PATCH` e `enabled: true`.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "customer_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "api_version": {
                      "description": "A versão do corpo, fixada na criação",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused",
                        "disabled"
                      ],
                      "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                    },
                    "pause_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "previous_secret_valid_until": {
                      "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "name",
                    "url",
                    "events",
                    "customer_fields",
                    "api_version",
                    "status",
                    "pause_reason",
                    "previous_secret_valid_until",
                    "livemode",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                  "name": "Meu sistema",
                  "url": "https://api.seusistema.com.br/torqyn",
                  "events": [
                    "message.delivered",
                    "message.failed",
                    "appointment.created"
                  ],
                  "customer_fields": [],
                  "api_version": "2026-10-01",
                  "status": "disabled",
                  "pause_reason": null,
                  "previous_secret_valid_until": null,
                  "livemode": false,
                  "created_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}/pause": {
      "post": {
        "operationId": "pauseWebhookEndpoint",
        "summary": "Pausar um endpoint",
        "description": "As entregas param e esperam na fila até reativar (útil durante uma manutenção do seu lado).",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "customer_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "api_version": {
                      "description": "A versão do corpo, fixada na criação",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused",
                        "disabled"
                      ],
                      "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                    },
                    "pause_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "previous_secret_valid_until": {
                      "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "name",
                    "url",
                    "events",
                    "customer_fields",
                    "api_version",
                    "status",
                    "pause_reason",
                    "previous_secret_valid_until",
                    "livemode",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                  "name": "Meu sistema",
                  "url": "https://api.seusistema.com.br/torqyn",
                  "events": [
                    "message.delivered",
                    "message.failed",
                    "appointment.created"
                  ],
                  "customer_fields": [],
                  "api_version": "2026-10-01",
                  "status": "paused",
                  "pause_reason": "pausado pelo dono",
                  "previous_secret_valid_until": null,
                  "livemode": false,
                  "created_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}/resume": {
      "post": {
        "operationId": "resumeWebhookEndpoint",
        "summary": "Reativar um endpoint",
        "description": "Volta a entregar o que ficou na fila, inclusive depois da pausa automática por falhas seguidas.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_endpoint"
                    },
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "customer_fields": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "api_version": {
                      "description": "A versão do corpo, fixada na criação",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "paused",
                        "disabled"
                      ],
                      "description": "`paused`: pausado pelo dono ou por falhas seguidas; as entregas esperam"
                    },
                    "pause_reason": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "previous_secret_valid_until": {
                      "description": "Durante a rotação, até quando o segredo anterior ainda assina junto",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "livemode": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "name",
                    "url",
                    "events",
                    "customer_fields",
                    "api_version",
                    "status",
                    "pause_reason",
                    "previous_secret_valid_until",
                    "livemode",
                    "created_at"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "4d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                  "name": "Meu sistema",
                  "url": "https://api.seusistema.com.br/torqyn",
                  "events": [
                    "message.delivered",
                    "message.failed",
                    "appointment.created"
                  ],
                  "customer_fields": [],
                  "api_version": "2026-10-01",
                  "status": "active",
                  "pause_reason": null,
                  "previous_secret_valid_until": null,
                  "livemode": false,
                  "created_at": "2026-10-01T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "Trocar o segredo de um endpoint",
        "description": "Gera um segredo novo, devolvido só nesta resposta. Por 24 h cada entrega leva as duas assinaturas (`v1=<novo>,v1=<anterior>`): troque o segredo no seu sistema nesse meio-tempo, sem perder nenhum evento.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_secret"
                    },
                    "secret": {
                      "type": "string"
                    },
                    "previous_secret_valid_until": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "secret",
                    "previous_secret_valid_until"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_secret",
                  "secret": "whsec_9aT3kLp0Qz7xVb2Nc5Rm8Wd1Ye4Hf6Us",
                  "previous_secret_valid_until": "2026-10-02T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`, `idempotency_key_required`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_key_in_use`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`idempotency_key_reused`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{id}/test": {
      "post": {
        "operationId": "testWebhookEndpoint",
        "summary": "Mandar um evento de teste",
        "description": "Manda agora um evento `ping`, assinado como os outros, e devolve o que o seu servidor respondeu. Não conta para a pausa por falhas.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-torqyn-scope": "webhooks:write",
        "parameters": [
          {
            "$ref": "#/components/parameters/TorqynVersion"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso",
            "headers": {
              "Torqyn-Request-Id": {
                "$ref": "#/components/headers/TorqynRequestId"
              },
              "Torqyn-Version": {
                "$ref": "#/components/headers/TorqynVersion"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "webhook_test"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "status": {
                      "anyOf": [
                        {
                          "type": "integer",
                          "minimum": -9007199254740991,
                          "maximum": 9007199254740991
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "O status HTTP que o seu servidor respondeu"
                    },
                    "duration_ms": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "object",
                    "ok",
                    "status",
                    "duration_ms",
                    "error"
                  ],
                  "additionalProperties": false
                },
                "example": {
                  "object": "webhook_test",
                  "ok": true,
                  "status": 200,
                  "duration_ms": 84,
                  "error": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`, `invalid_version`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`forbidden_scope`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`not_found`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error`",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "ping": {
      "post": {
        "summary": "Evento de teste",
        "description": "O botão \"Enviar evento de teste\" e `POST /v1/webhook-endpoints/{id}/test`. Todo endpoint recebe, escolhido ou não.",
        "x-torqyn-event": "ping",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "ping",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "ping",
                    "message": "Evento de teste: se chegou, o endereço e a assinatura estão certos."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "contact.opted_out": {
      "post": {
        "summary": "Contato pediu para sair",
        "description": "A pessoa pediu para não receber mais mensagens (em qualquer canal). Pare de mandar mensagens de marketing para ela no seu sistema também.",
        "x-torqyn-event": "contact.opted_out",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "contact.opted_out",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "contact",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    },
                    "channel": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "message.received": {
      "post": {
        "summary": "Mensagem recebida",
        "description": "O contato mandou uma mensagem. O corpo traz a conversa e o canal, não o texto: o conteúdo é dado pessoal e fica na Torqyn.",
        "x-torqyn-event": "message.received",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "message.received",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "message",
                    "id": "7e1f3a5b-2c4d-4e6f-8a9b-0c1d2e3f4a5b",
                    "direction": "inbound",
                    "status": "received",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "channel": "whatsapp",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "message.sent": {
      "post": {
        "summary": "Mensagem enviada",
        "description": "Uma mensagem nossa (da IA ou do time) saiu para o canal.",
        "x-torqyn-event": "message.sent",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "message.sent",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "message",
                    "id": "3a5c7e9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
                    "direction": "outbound",
                    "status": "sent",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "channel": "whatsapp",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "message.delivered": {
      "post": {
        "summary": "Mensagem entregue",
        "description": "O canal confirmou que a mensagem chegou ao aparelho da pessoa.",
        "x-torqyn-event": "message.delivered",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "message.delivered",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "message",
                    "id": "3a5c7e9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
                    "direction": "outbound",
                    "status": "delivered",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "channel": "whatsapp",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "message.read": {
      "post": {
        "summary": "Mensagem lida",
        "description": "A pessoa abriu a mensagem (quando o canal informa leitura).",
        "x-torqyn-event": "message.read",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "message.read",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "message",
                    "id": "3a5c7e9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
                    "direction": "outbound",
                    "status": "read",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "channel": "whatsapp",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "message.failed": {
      "post": {
        "summary": "Mensagem não entregue",
        "description": "O canal recusou a mensagem. O motivo aparece no painel, na conversa.",
        "x-torqyn-event": "message.failed",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "message.failed",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "message",
                    "id": "3a5c7e9b-1d2f-4a6b-8c0d-2e4f6a8b0c1d",
                    "direction": "outbound",
                    "status": "failed",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "channel": "whatsapp",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "conversation.handed_off": {
      "post": {
        "summary": "Conversa passou para o time",
        "description": "A IA chamou alguém do time, ou alguém do time assumiu a conversa.",
        "x-torqyn-event": "conversation.handed_off",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "conversation.handed_off",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "conversation",
                    "id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "channel": "whatsapp",
                    "handed_off_by": "ai",
                    "case_id": "2c4e6a8b-1d3f-4a5b-8c7d-9e0f1a2b3c4d",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "appointment.created": {
      "post": {
        "summary": "Horário marcado",
        "description": "Um horário foi marcado, pela conversa, pela página ou pelo time.",
        "x-torqyn-event": "appointment.created",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "appointment.created",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "appointment",
                    "case_id": "2c4e6a8b-1d3f-4a5b-8c7d-9e0f1a2b3c4d",
                    "flow": "scheduling",
                    "starts_at": "2026-10-03T18:00:00.000Z",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "payment.succeeded": {
      "post": {
        "summary": "Pagamento confirmado",
        "description": "O provedor de pagamento confirmou um pagamento na conta de recebimento do negócio.",
        "x-torqyn-event": "payment.succeeded",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "payment.succeeded",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "payment",
                    "amount_cents": 15000,
                    "currency": "BRL",
                    "case_id": "2c4e6a8b-1d3f-4a5b-8c7d-9e0f1a2b3c4d",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "case.stage_changed": {
      "post": {
        "summary": "Caso mudou de etapa",
        "description": "O caso mudou de coluna no quadro, com a etapa de antes e a de agora.",
        "x-torqyn-event": "case.stage_changed",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "case.stage_changed",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "case",
                    "id": "2c4e6a8b-1d3f-4a5b-8c7d-9e0f1a2b3c4d",
                    "flow": "sales",
                    "stage": "proposal_sent",
                    "previous_stage": "engaged",
                    "value_cents": 15000,
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "case.won": {
      "post": {
        "summary": "Caso ganho",
        "description": "O caso fechou com resultado bom (venda, comparecimento, atendimento resolvido), confirmado na origem ou marcado pelo time.",
        "x-torqyn-event": "case.won",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "case.won",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "case",
                    "id": "2c4e6a8b-1d3f-4a5b-8c7d-9e0f1a2b3c4d",
                    "flow": "sales",
                    "stage": "won",
                    "result": "won",
                    "outcome": "sale_won",
                    "value_cents": 15000,
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "case.lost": {
      "post": {
        "summary": "Caso perdido",
        "description": "O caso fechou sem o resultado (perdido, faltou, cancelado).",
        "x-torqyn-event": "case.lost",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "case.lost",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "case",
                    "id": "2c4e6a8b-1d3f-4a5b-8c7d-9e0f1a2b3c4d",
                    "flow": "sales",
                    "stage": "lost",
                    "result": "lost",
                    "outcome": "sale_lost",
                    "value_cents": 15000,
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "event.delivered": {
      "post": {
        "summary": "Evento entregue",
        "description": "Um evento que o seu sistema mandou (`POST /v1/events`) virou mensagem.",
        "x-torqyn-event": "event.delivered",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "event.delivered",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "event",
                    "type": "consulta_amanha",
                    "status": "delivered",
                    "reason": null,
                    "via": "template",
                    "channel": "whatsapp",
                    "conversation_id": "9b2f4c1e-7d3a-4e5f-8a6b-1c2d3e4f5a6b",
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    },
    "event.failed": {
      "post": {
        "summary": "Evento não entregue",
        "description": "Um evento que o seu sistema mandou não virou mensagem, e o motivo vem no corpo.",
        "x-torqyn-event": "event.failed",
        "parameters": [
          {
            "name": "Torqyn-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<segundos>,v1=<hmac>`; na troca do segredo, dois `v1`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Event-Type",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Torqyn-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEnvelope"
              },
              "example": {
                "id": "8c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                "type": "event.failed",
                "api_version": "2026-10-01",
                "created": "2026-10-01T12:00:00.000Z",
                "livemode": true,
                "account": "1f2e3d4c-5b6a-4978-8695-a4b3c2d1e0f9",
                "data": {
                  "object": {
                    "object": "event",
                    "type": "consulta_amanha",
                    "status": "failed",
                    "reason": "outside_window",
                    "via": null,
                    "channel": null,
                    "conversation_id": null,
                    "contact": {
                      "id": "5b7c2d1e-8f3a-4b6c-9d2e-1f4a5b6c7d8e",
                      "external_id": "fam-123"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Recebido. Qualquer outra resposta, ou nada em 10 s, é falha."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Chave de API: `tq_test_…` abre a conta de teste, `tq_live_…` a de produção. Só no servidor; nunca no navegador nem na query string."
      }
    },
    "parameters": {
      "TorqynVersion": {
        "name": "Torqyn-Version",
        "in": "header",
        "required": false,
        "description": "Versão datada da API. Sem ela, vale a mais recente (2026-10-01).",
        "schema": {
          "type": "string",
          "enum": [
            "2026-10-01"
          ]
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Um valor único por operação (ex.: um UUID). Repetir a mesma chave em 24 h devolve a mesma resposta; com outro corpo, 422.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        }
      }
    },
    "headers": {
      "TorqynRequestId": {
        "description": "Id desta requisição; mande-o ao suporte quando algo der errado.",
        "schema": {
          "type": "string"
        }
      },
      "TorqynVersion": {
        "description": "A versão da API que respondeu.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "code",
          "request_id"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Link para https://torqyn.com/docs/erros#<code>"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_version",
              "idempotency_key_required",
              "unauthorized",
              "forbidden_scope",
              "not_found",
              "conflict",
              "rejected",
              "opted_out",
              "idempotency_key_in_use",
              "payload_too_large",
              "unsupported_media_type",
              "idempotency_key_reused",
              "rate_limited",
              "internal_error"
            ]
          },
          "detail": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "description": "O mesmo do cabeçalho Torqyn-Request-Id"
          }
        }
      },
      "WebhookEnvelope": {
        "type": "object",
        "required": [
          "id",
          "type",
          "api_version",
          "created",
          "livemode",
          "account",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Id do evento: o mesmo em toda nova tentativa e no reenvio."
          },
          "type": {
            "type": "string"
          },
          "api_version": {
            "type": "string",
            "description": "A versão presa ao endpoint quando ele foi criado."
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "livemode": {
            "type": "boolean",
            "description": "false na conta de teste."
          },
          "account": {
            "type": "string",
            "description": "Id da conta que gerou o evento."
          },
          "data": {
            "type": "object",
            "required": [
              "object"
            ],
            "properties": {
              "object": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        }
      }
    }
  }
}
