{
  "openapi": "3.0.3",
  "info": {
    "title": "Hooklane Management API",
    "version": "1.0.0",
    "description": "API pública de gerenciamento do Hooklane. Cobre exatamente os endpoints implementados em server/routes/v1.ts nesta entrega — nenhum endpoint listado aqui é hipotético. Esta API NUNCA recebe eventos de sistemas terceiros — isso acontece em `https://hooklane.shop/hooks/{token}`, uma URL completamente separada, sem autenticação por chave de API, documentada apenas como referência em `x-ingest-url` nos schemas de webhook.\n\nLimites de frequência: 120 requisições por minuto **por chave**, mais limites por ação na criação (10 a cada 10 minutos e 20 por hora) e na atualização/exclusão de webhooks (60 a cada 10 minutos), contados por conta. Ao estourar qualquer um deles a resposta é `429` com o cabeçalho `Retry-After` e `code: rate_limited`. Uma chave de API nunca recebe `captcha_required` — a verificação de segurança existe apenas nas telas do painel.\n"
  },
  "servers": [
    {
      "url": "https://hooklane.shop/api/v1"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "hk_live_...",
        "description": "Gere em Configurações → Chaves de API no painel, ou via `POST /api/keys` (rota do painel, autenticada por sessão). Uma chave sem `scopes` definido tem acesso total.\n"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "ValidationIssue": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "wh_abc123"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "token": {
            "type": "string",
            "description": "Identificador na URL pública de entrada"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          },
          "integrationType": {
            "type": "string",
            "enum": [
              "normal",
              "discord"
            ]
          },
          "hasSecret": {
            "type": "boolean"
          },
          "secretRotatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "description": "URL pública de ENTRADA (x-ingest-url) — para onde sistemas terceiros enviam eventos, nunca para gerenciamento"
          },
          "eventCount": {
            "type": "integer"
          },
          "destinationCount": {
            "type": "integer"
          }
        }
      },
      "Destination": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "webhookId": {
            "type": "string"
          },
          "webhookName": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "Mascarada quando kind=discord"
          },
          "active": {
            "type": "boolean"
          },
          "kind": {
            "type": "string",
            "enum": [
              "generic",
              "discord"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "successCount": {
            "type": "integer"
          },
          "failureCount": {
            "type": "integer"
          }
        }
      },
      "EventSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "webhookId": {
            "type": "string"
          },
          "method": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "delivered",
              "failed",
              "partial",
              "no_destination"
            ]
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          },
          "size": {
            "type": "integer"
          }
        }
      },
      "TemplateContent": {
        "description": "Uma de três formas — o campo `mode` determina qual",
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "simple"
                ]
              },
              "text": {
                "type": "string",
                "maxLength": 2000
              }
            },
            "required": [
              "mode",
              "text"
            ]
          },
          {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "embed"
                ]
              },
              "text": {
                "type": "string",
                "maxLength": 2000
              },
              "embeds": {
                "type": "array",
                "maxItems": 10,
                "items": {
                  "type": "object",
                  "properties": {
                    "title": {
                      "type": "string",
                      "maxLength": 256
                    },
                    "description": {
                      "type": "string",
                      "maxLength": 4096
                    },
                    "url": {
                      "type": "string"
                    },
                    "color": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 16777215
                    },
                    "fields": {
                      "type": "array",
                      "maxItems": 25,
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string",
                            "maxLength": 256
                          },
                          "value": {
                            "type": "string",
                            "maxLength": 1024
                          },
                          "inline": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            },
            "required": [
              "mode",
              "embeds"
            ]
          },
          {
            "type": "object",
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "components_v2"
                ]
              },
              "components": {
                "type": "array",
                "maxItems": 40,
                "items": {
                  "type": "object",
                  "description": "container | text_display | separator | section | thumbnail | media_gallery | action_row"
                }
              }
            },
            "required": [
              "mode",
              "components"
            ]
          }
        ]
      },
      "DiscordTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "webhookId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "simple",
              "embed",
              "components_v2"
            ]
          },
          "content": {
            "$ref": "#/components/schemas/TemplateContent"
          },
          "isDefault": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DiscordRoute": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "webhookId": {
            "type": "string"
          },
          "destinationId": {
            "type": "string",
            "nullable": true
          },
          "templateId": {
            "type": "string"
          },
          "eventTypeFilter": {
            "type": "string",
            "nullable": true
          },
          "condition": {
            "type": "object",
            "nullable": true,
            "properties": {
              "field": {
                "type": "string"
              },
              "operator": {
                "type": "string",
                "enum": [
                  "eq",
                  "neq",
                  "exists",
                  "not_exists",
                  "contains",
                  "gt",
                  "lt"
                ]
              },
              "value": {
                "type": "string"
              }
            }
          },
          "skipIfNoMatch": {
            "type": "boolean"
          },
          "priority": {
            "type": "integer"
          },
          "enabled": {
            "type": "boolean"
          }
        }
      }
    },
    "parameters": {
      "WebhookId": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "TemplateId": {
        "name": "templateId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "RouteId": {
        "name": "routeId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Chave ausente, inválida ou revogada",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Escopo insuficiente para esta operação, ou teto técnico de webhooks do workspace atingido (code: webhook_cap_reached). A quantidade de webhooks não é limite de plano.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "UsageLimitReached": {
        "description": "Workspace restrito por uso (code: usage_limit_reached): a franquia do plano foi ultrapassada e a janela de 3 dias para regularizar terminou. Nenhum dado é apagado; faça upgrade ou reduza o consumo para voltar a operar.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Recurso não encontrado (ou pertence a outra conta — nunca distinguido de \"não existe\")",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Limite de frequência atingido (code: rate_limited). Repita após Retry-After segundos.",
        "headers": {
          "Retry-After": {
            "description": "Segundos até a janela reabrir",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "Template ou config estruturalmente inválido",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string"
                },
                "issues": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ValidationIssue"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "paths": {
    "/integration-types": {
      "get": {
        "summary": "Lista os tipos de webhook suportados por este servidor",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "hasConfig": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "summary": "Lista webhooks",
        "description": "Escopo: webhooks:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "summary": "Cria um webhook (Normal ou de qualquer tipo registrado)",
        "description": "Escopo: webhooks:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 300,
                    "nullable": true
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "normal",
                      "discord"
                    ],
                    "default": "normal"
                  },
                  "config": {
                    "type": "object",
                    "description": "Obrigatório quando type != normal. Para discord: {discordWebhookUrl, initialMode?}"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criado",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/UsageLimitReached"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "summary": "Consulta um webhook",
        "description": "Escopo: webhooks:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "summary": "Atualiza nome, descrição ou status (active/paused)",
        "description": "Escopo: webhooks:write",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string",
                    "nullable": true
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "summary": "Exclui um webhook e todos os seus dados (eventos, destinos, entregas)",
        "description": "Escopo: webhooks:delete",
        "responses": {
          "204": {
            "description": "Excluído"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{id}/secret": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "summary": "Rotaciona o signing secret do webhook",
        "description": "Escopo: webhooks:write",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "secret": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/destinations": {
      "get": {
        "summary": "Lista destinos (opcionalmente filtrado por webhookId)",
        "description": "Escopo: destinations:read",
        "parameters": [
          {
            "name": "webhookId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Destination"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Cria um destino genérico",
        "description": "Escopo: destinations:write. Validado contra SSRF, igual ao painel.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "webhookId": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string"
                  },
                  "active": {
                    "type": "boolean",
                    "default": true
                  }
                },
                "required": [
                  "webhookId",
                  "name",
                  "url"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criado"
          },
          "400": {
            "description": "URL insegura ou inválida (SSRF)"
          }
        }
      }
    },
    "/destinations/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "patch": {
        "summary": "Atualiza nome, URL ou status de um destino",
        "description": "Escopo: destinations:write",
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "summary": "Exclui um destino",
        "description": "Escopo: destinations:delete",
        "responses": {
          "204": {
            "description": "Excluído"
          }
        }
      }
    },
    "/events": {
      "get": {
        "summary": "Lista eventos, paginado",
        "description": "Escopo: events:read",
        "parameters": [
          {
            "name": "webhookId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EventSummary"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "page_size": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/events/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "summary": "Consulta um evento com todas as suas tentativas de entrega",
        "description": "Escopo: events:read",
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/events/{id}/replay": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "post": {
        "summary": "Reenvia um evento (a todos os destinos ativos, ou a um específico)",
        "description": "Escopo: events:write",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "destinationId": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Nenhum destino ativo configurado"
          },
          "402": {
            "$ref": "#/components/responses/UsageLimitReached"
          }
        }
      }
    },
    "/retries": {
      "get": {
        "summary": "Lista retries agendados",
        "description": "Escopo: events:read",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "pending"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/retries/{id}/run": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "post": {
        "summary": "Executa um retry agendado imediatamente",
        "description": "Escopo: events:write",
        "responses": {
          "200": {
            "description": "OK"
          },
          "402": {
            "$ref": "#/components/responses/UsageLimitReached"
          },
          "409": {
            "description": "Este retry já foi processado"
          }
        }
      }
    },
    "/audit-log": {
      "get": {
        "summary": "Lista as últimas alterações feitas via API (nunca via painel)",
        "description": "Escopo: webhooks:read",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/webhooks/{id}/discord/config": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "summary": "Consulta a configuração Discord (nome de exibição, avatar, allowed_mentions)",
        "description": "Escopo: discord:read",
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "Este webhook não é do tipo Discord"
          }
        }
      },
      "patch": {
        "summary": "Atualiza a configuração Discord",
        "description": "Escopo: discord:write",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/discord/destinations/{destinationId}/url": {
      "parameters": [
        {
          "name": "destinationId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "patch": {
        "summary": "Substitui a URL da webhook do Discord (rotação de credencial)",
        "description": "Escopo: discord:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "discordWebhookUrl": {
                    "type": "string"
                  }
                },
                "required": [
                  "discordWebhookUrl"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          },
          "400": {
            "description": "URL inválida"
          }
        }
      }
    },
    "/webhooks/{id}/discord/templates": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "summary": "Lista os templates de mensagem do webhook",
        "description": "Escopo: discord:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DiscordTemplate"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Cria um template",
        "description": "Escopo: discord:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "content": {
                    "$ref": "#/components/schemas/TemplateContent"
                  },
                  "isDefault": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criado"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    },
    "/webhooks/{id}/discord/templates/{templateId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        },
        {
          "$ref": "#/components/parameters/TemplateId"
        }
      ],
      "get": {
        "summary": "Consulta um template",
        "description": "Escopo: discord:read",
        "responses": {
          "200": {
            "description": "OK"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "summary": "Atualiza um template",
        "description": "Escopo: discord:write",
        "responses": {
          "200": {
            "description": "OK"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      },
      "delete": {
        "summary": "Exclui um template (falha se estiver em uso por uma regra de roteamento)",
        "description": "Escopo: discord:delete",
        "responses": {
          "204": {
            "description": "Excluído"
          },
          "409": {
            "description": "Template em uso por uma regra de roteamento"
          }
        }
      }
    },
    "/webhooks/{id}/discord/routes": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "summary": "Lista as regras de roteamento",
        "description": "Escopo: discord:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DiscordRoute"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Cria uma regra de roteamento",
        "description": "Escopo: discord:write",
        "responses": {
          "201": {
            "description": "Criado"
          }
        }
      }
    },
    "/webhooks/{id}/discord/routes/{routeId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        },
        {
          "$ref": "#/components/parameters/RouteId"
        }
      ],
      "patch": {
        "summary": "Atualiza uma regra de roteamento",
        "description": "Escopo: discord:write",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      },
      "delete": {
        "summary": "Exclui uma regra de roteamento",
        "description": "Escopo: discord:delete",
        "responses": {
          "204": {
            "description": "Excluído"
          }
        }
      }
    },
    "/webhooks/{id}/discord/preview": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "summary": "Renderiza um template contra um payload de exemplo — nunca envia nada ao Discord",
        "description": "Escopo: discord:read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "$ref": "#/components/schemas/TemplateContent"
                  },
                  "samplePayload": {
                    "type": "object"
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/webhooks/{id}/discord/test-send": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "summary": "Envia uma mensagem REAL ao canal do Discord configurado",
        "description": "Escopos: discord:write E test:send (ambos obrigatórios). Usa exatamente a mesma validação e o mesmo builder de payload do envio real de eventos.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "$ref": "#/components/schemas/TemplateContent"
                  },
                  "samplePayload": {
                    "type": "object"
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK — verifique data.ok, um 200 aqui não garante que o Discord aceitou o envio"
          },
          "400": {
            "description": "Nenhum destino Discord ativo configurado"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          }
        }
      }
    }
  }
}
