{
  "openapi": "3.0.3",
  "info": {
    "title": "Notifique API. OAuth 2.1",
    "description": "Authorization Server OAuth 2.1 com PKCE obrigatório. Registre clientes, autorize usuários e obtenha access tokens para chamar `/v1/*`. Issuer: `https://api.notifique.dev`.",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://api.notifique.dev",
      "description": "Produção"
    }
  ],
  "tags": [
    {
      "name": "Metadados",
      "description": "Discovery RFC 8414, chaves públicas JWT e metadados do recurso MCP."
    },
    {
      "name": "OAuth",
      "description": "Registro de clientes, autorização, tokens e revogação."
    },
    {
      "name": "OAuth Apps",
      "description": "Apps OAuth do workspace (painel Developer → OAuth Apps)."
    }
  ],
  "paths": {
    "/.well-known/oauth-authorization-server": {
      "get": {
        "tags": [
          "Metadados"
        ],
        "summary": "Metadados do Authorization Server",
        "description": "Retorna URLs dos endpoints OAuth (`authorization_endpoint`, `token_endpoint`, `registration_endpoint`, etc.) conforme RFC 8414.",
        "operationId": "ntfOauth_getAuthorizationServerMetadata",
        "responses": {
          "200": {
            "description": "Documento de metadados OAuth 2.0.",
            "content": {
              "application/json": {
                "example": {
                  "issuer": "https://api.notifique.dev",
                  "authorization_endpoint": "https://api.notifique.dev/oauth/authorize",
                  "token_endpoint": "https://api.notifique.dev/oauth/token",
                  "registration_endpoint": "https://api.notifique.dev/oauth/register",
                  "revocation_endpoint": "https://api.notifique.dev/oauth/revoke",
                  "jwks_uri": "https://api.notifique.dev/.well-known/jwks.json",
                  "response_types_supported": [
                    "code"
                  ],
                  "grant_types_supported": [
                    "authorization_code",
                    "refresh_token"
                  ],
                  "code_challenge_methods_supported": [
                    "S256"
                  ],
                  "token_endpoint_auth_methods_supported": [
                    "client_secret_basic",
                    "none"
                  ],
                  "scopes_supported": [
                    "email:send",
                    "whatsapp:send",
                    "sms:send",
                    "contacts:read"
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_GetAuthorizationServerMetadataResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "tags": [
          "Metadados"
        ],
        "summary": "Chaves públicas (JWKS)",
        "description": "Chaves EdDSA para validar access tokens JWT localmente.",
        "operationId": "ntfOauth_getJwks",
        "responses": {
          "200": {
            "description": "JSON Web Key Set.",
            "content": {
              "application/json": {
                "example": {
                  "keys": [
                    {
                      "kty": "OKP",
                      "crv": "Ed25519",
                      "kid": "ntf-oauth-2026",
                      "use": "sig",
                      "alg": "EdDSA"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_GetJwksResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "tags": [
          "Metadados"
        ],
        "summary": "Metadados do recurso MCP",
        "description": "Usado por hosts MCP (ChatGPT, Claude, Gemini) para descobrir o Authorization Server do recurso `https://mcp.notifique.dev/mcp`.",
        "operationId": "ntfOauth_getProtectedResourceMetadata",
        "responses": {
          "200": {
            "description": "Metadados do recurso protegido.",
            "content": {
              "application/json": {
                "example": {
                  "resource": "https://mcp.notifique.dev/mcp",
                  "authorization_servers": [
                    "https://api.notifique.dev"
                  ],
                  "scopes_supported": [
                    "email:send",
                    "whatsapp:send",
                    "sms:send"
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_GetProtectedResourceMetadataResponse"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/register": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Registrar cliente (DCR)",
        "description": "Dynamic Client Registration (RFC 7591). Cria um cliente OAuth — pelo código ou antes do fluxo MCP. O `client_secret` só é retornado uma vez para clientes confidenciais.",
        "operationId": "ntfOauth_registerClient",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NtfOauth_ClientRegistration"
              },
              "examples": {
                "web_confidencial": {
                  "summary": "App web com backend",
                  "value": {
                    "client_name": "Meu App",
                    "redirect_uris": [
                      "https://meuapp.com/oauth/callback"
                    ],
                    "grant_types": [
                      "authorization_code",
                      "refresh_token"
                    ],
                    "response_types": [
                      "code"
                    ],
                    "token_endpoint_auth_method": "client_secret_basic",
                    "scope": "email:send"
                  }
                },
                "cli_publico": {
                  "summary": "CLI local (público + PKCE)",
                  "value": {
                    "client_name": "Minha CLI",
                    "redirect_uris": [
                      "http://127.0.0.1:8765/callback"
                    ],
                    "grant_types": [
                      "authorization_code",
                      "refresh_token"
                    ],
                    "response_types": [
                      "code"
                    ],
                    "token_endpoint_auth_method": "none",
                    "scope": "email:send"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Cliente registrado.",
            "content": {
              "application/json": {
                "example": {
                  "client_id": "ntf_oauth_cl_abc123",
                  "client_secret": "ntf_oauth_cs_xyz789",
                  "client_name": "Meu App",
                  "redirect_uris": [
                    "https://meuapp.com/oauth/callback"
                  ],
                  "grant_types": [
                    "authorization_code",
                    "refresh_token"
                  ],
                  "response_types": [
                    "code"
                  ],
                  "token_endpoint_auth_method": "client_secret_basic",
                  "scope": "email:send",
                  "client_id_issued_at": 1735689600
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_RegisterClientResponse"
                }
              }
            }
          },
          "400": {
            "description": "Payload inválido (redirect URI, grant type, etc.)."
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Autorizar (browser)",
        "description": "Abre a tela de login e consentimento. **PKCE obrigatório** (`code_challenge` + `S256`). Redireciona para `redirect_uri` com `code` e `state`.",
        "operationId": "ntfOauth_authorize",
        "parameters": [
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID do cliente OAuth."
          },
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            },
            "description": "Sempre `code` (authorization code)."
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "Deve coincidir exatamente com uma URI registrada."
          },
          {
            "name": "scope",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Escopos separados por espaço (ex.: `email:send contacts:read`)."
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Valor aleatório — valide no callback contra CSRF."
          },
          {
            "name": "code_challenge",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "BASE64URL(SHA256(code_verifier))."
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            },
            "description": "Sempre `S256`."
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect para login ou para `redirect_uri?code=...&state=...` após aprovação.",
            "headers": {
              "Location": {
                "description": "URL de destino (login ou callback com `code` e `state`).",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "400": {
            "description": "Parâmetros inválidos ou PKCE ausente."
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Obter ou renovar tokens",
        "description": "Troca `authorization_code` por tokens (com `code_verifier`) ou renova com `refresh_token`. Refresh tokens rotacionam a cada uso.",
        "operationId": "ntfOauth_token",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/NtfOauth_AuthorizationCodeGrant"
                  },
                  {
                    "$ref": "#/components/schemas/NtfOauth_RefreshTokenGrant"
                  }
                ]
              },
              "examples": {
                "authorization_code": {
                  "summary": "Trocar code por tokens",
                  "value": {
                    "grant_type": "authorization_code",
                    "code": "auth_code_abc",
                    "redirect_uri": "https://meuapp.com/oauth/callback",
                    "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
                  }
                },
                "refresh_token": {
                  "summary": "Renovar access token",
                  "value": {
                    "grant_type": "refresh_token",
                    "refresh_token": "rt_opaque_xyz"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens emitidos.",
            "content": {
              "application/json": {
                "example": {
                  "access_token": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...",
                  "token_type": "Bearer",
                  "expires_in": 900,
                  "refresh_token": "rt_opaque_new",
                  "scope": "email:send"
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Grant inválido (`invalid_grant`, PKCE incorreto, code expirado)."
          },
          "401": {
            "description": "Cliente não autenticado (confidencial sem secret válido)."
          }
        }
      }
    },
    "/oauth/revoke": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Revogar token",
        "description": "Invalida refresh token (e o grant associado). Clientes confidenciais autenticam com `client_secret_basic`.",
        "operationId": "ntfOauth_revoke",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "Refresh token (ou access token) a revogar."
                  },
                  "token_type_hint": {
                    "type": "string",
                    "enum": [
                      "refresh_token",
                      "access_token"
                    ]
                  }
                }
              },
              "example": {
                "token": "rt_opaque_xyz",
                "token_type_hint": "refresh_token"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token revogado (resposta vazia ou 200).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_RevokeResponse"
                },
                "example": {
                  "success": true
                }
              }
            }
          }
        }
      }
    },
    "/v1/oauth/apps": {
      "get": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Listar OAuth apps do workspace",
        "description": "Lista apps criados em **Developer → OAuth Apps**. Escopo `oauth_apps:read`.",
        "operationId": "ntfOauth_listWorkspaceApps",
        "responses": {
          "200": {
            "description": "Lista de apps.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "cloauthapp_01H...",
                      "name": "Meu SaaS",
                      "clientId": "ntf_oauth_cl_abc123",
                      "redirectUris": [
                        "https://meuapp.com/oauth/callback"
                      ],
                      "scopes": [
                        "email:send",
                        "contacts:read"
                      ],
                      "createdAt": "2026-08-01T10:00:00.000Z"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_ListWorkspaceAppsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Criar OAuth app",
        "description": "Cria app OAuth do workspace. `clientSecret` retornado **uma vez**. Escopo `oauth_apps:manage`.",
        "operationId": "ntfOauth_createWorkspaceApp",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NtfOauth_WorkspaceAppCreate"
              },
              "example": {
                "name": "Meu SaaS",
                "redirectUris": [
                  "https://meuapp.com/oauth/callback"
                ],
                "allowedScopes": [
                  "email:send",
                  "contacts:read"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "App criado.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "cloauthapp_01HNEW...",
                    "name": "Meu SaaS",
                    "clientId": "ntf_oauth_cl_abc123",
                    "clientSecret": "ntf_oauth_cs_shown_once_xyz...",
                    "redirectUris": [
                      "https://meuapp.com/oauth/callback"
                    ],
                    "scopes": [
                      "email:send",
                      "contacts:read"
                    ]
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_CreateWorkspaceAppResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/NtfOauth_BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          }
        }
      }
    },
    "/v1/oauth/apps/{id}": {
      "get": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Consultar OAuth app",
        "operationId": "ntfOauth_getWorkspaceApp",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App encontrado (sem secret).",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "cloauthapp_01H...",
                    "name": "Meu SaaS",
                    "clientId": "ntf_oauth_cl_abc123",
                    "redirectUris": [
                      "https://meuapp.com/oauth/callback"
                    ],
                    "scopes": [
                      "email:send"
                    ]
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_GetWorkspaceAppResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NtfOauth_NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Atualizar OAuth app",
        "description": "Altera nome, redirect URIs ou escopos padrão. Escopo `oauth_apps:manage`.",
        "operationId": "ntfOauth_updateWorkspaceApp",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NtfOauth_WorkspaceAppPatch"
              },
              "example": {
                "name": "Meu SaaS v2",
                "allowedScopes": [
                  "email:send",
                  "whatsapp:send"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "App atualizado.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "cloauthapp_01H...",
                    "name": "Meu SaaS v2"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_UpdateWorkspaceAppResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/NtfOauth_BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NtfOauth_NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Excluir OAuth app",
        "description": "Revoga o app e grants associados. Escopo `oauth_apps:manage`.",
        "operationId": "ntfOauth_deleteWorkspaceApp",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "App removido.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "cloauthapp_01H...",
                    "deleted": true
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_DeleteWorkspaceAppResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NtfOauth_NotFound"
          }
        }
      }
    },
    "/v1/oauth/apps/{id}/rotate-secret": {
      "post": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Rotacionar client secret",
        "description": "Gera novo `clientSecret` (exibido uma vez). Escopo `oauth_apps:manage`.",
        "operationId": "ntfOauth_rotateWorkspaceAppSecret",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Novo secret emitido.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "cloauthapp_01H...",
                    "clientId": "ntf_oauth_cl_abc123",
                    "clientSecret": "ntf_oauth_cs_new_shown_once..."
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_RotateWorkspaceAppSecretResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NtfOauth_NotFound"
          }
        }
      }
    },
    "/v1/oauth/connections": {
      "get": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Listar apps conectados",
        "description": "Grants ativos (usuários que autorizaram apps no workspace). Escopo `oauth_apps:read`.",
        "operationId": "ntfOauth_listConnections",
        "responses": {
          "200": {
            "description": "Lista de conexões.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": [
                    {
                      "id": "clconn_01H...",
                      "appId": "cloauthapp_01H...",
                      "appName": "Meu SaaS",
                      "userEmail": "user@empresa.com",
                      "scopes": [
                        "email:send"
                      ],
                      "createdAt": "2026-08-10T15:00:00.000Z"
                    }
                  ]
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_ListConnectionsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          }
        }
      }
    },
    "/v1/oauth/connections/{id}/revoke": {
      "post": {
        "tags": [
          "OAuth Apps"
        ],
        "summary": "Revogar conexão",
        "description": "Revoga o grant de um usuário/app conectado. Equivalente a **Apps conectados → Revogar** no painel. Escopo `oauth_apps:manage`.",
        "operationId": "ntfOauth_revokeConnection",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Conexão revogada.",
            "content": {
              "application/json": {
                "example": {
                  "success": true,
                  "data": {
                    "id": "clconn_01H...",
                    "revoked": true
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/ntfOauth_RevokeConnectionResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/NtfOauth_Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/NtfOauth_Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NtfOauth_NotFound"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "NtfOauth_AuthorizeResponse": {
        "type": "object",
        "additionalProperties": false,
        "description": "Authorize responde com HTTP 302 e body vazio; use o header `Location`.",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          }
        },
        "example": {
          "success": true
        }
      },
      "NtfOauth_ClientRegistration": {
        "type": "object",
        "required": [
          "client_name",
          "redirect_uris"
        ],
        "properties": {
          "client_name": {
            "type": "string",
            "description": "Nome exibido na tela de consentimento."
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "URIs de callback permitidas."
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "default": [
              "authorization_code",
              "refresh_token"
            ]
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "default": [
              "code"
            ]
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": [
              "client_secret_basic",
              "none"
            ],
            "default": "client_secret_basic"
          },
          "scope": {
            "type": "string",
            "description": "Escopos padrão do cliente, separados por espaço."
          }
        },
        "example": {
          "client_name": "string",
          "redirect_uris": [
            "https://example.com/resource"
          ],
          "grant_types": [
            "authorization_code",
            "refresh_token"
          ],
          "response_types": [
            "code"
          ],
          "token_endpoint_auth_method": "client_secret_basic",
          "scope": "string"
        }
      },
      "NtfOauth_AuthorizationCodeGrant": {
        "type": "object",
        "required": [
          "grant_type",
          "code",
          "redirect_uri",
          "code_verifier"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "authorization_code"
            ]
          },
          "code": {
            "type": "string"
          },
          "redirect_uri": {
            "type": "string",
            "format": "uri"
          },
          "code_verifier": {
            "type": "string"
          }
        },
        "example": {
          "grant_type": "authorization_code",
          "code": "string",
          "redirect_uri": "https://example.com/resource",
          "code_verifier": "string"
        }
      },
      "NtfOauth_RefreshTokenGrant": {
        "type": "object",
        "required": [
          "grant_type",
          "refresh_token"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "refresh_token"
            ]
          },
          "refresh_token": {
            "type": "string"
          }
        },
        "example": {
          "grant_type": "refresh_token",
          "refresh_token": "string"
        }
      },
      "NtfOauth_WorkspaceAppCreate": {
        "type": "object",
        "required": [
          "name",
          "redirectUris"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "allowedScopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Escopos padrão do app."
          }
        },
        "example": {
          "name": "Exemplo",
          "redirectUris": [
            "https://example.com/resource"
          ],
          "allowedScopes": [
            "string"
          ]
        }
      },
      "NtfOauth_WorkspaceAppPatch": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "allowedScopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "example": {
          "name": "Exemplo",
          "redirectUris": [
            "https://example.com/resource"
          ],
          "allowedScopes": [
            "string"
          ]
        }
      },
      "NtfOauth_Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string"
          }
        },
        "example": {
          "success": false,
          "error": "string",
          "message": "string",
          "code": "string"
        }
      },
      "NtfBinaryFileResponse": {
        "type": "string",
        "format": "binary",
        "description": "Conteúdo binário (download de arquivo ou mídia)."
      },
      "NtfCsvExportResponse": {
        "type": "string",
        "description": "Conteúdo CSV (exportação)."
      },
      "NtfEmptyJsonResponse": {
        "type": "object",
        "additionalProperties": false,
        "description": "Resposta JSON vazia (sucesso sem payload).",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          }
        },
        "example": {
          "success": true
        }
      },
      "ntfOauth_GetJwksResponse": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kty": {
                  "type": "string"
                },
                "crv": {
                  "type": "string"
                },
                "kid": {
                  "type": "string"
                },
                "use": {
                  "type": "string"
                },
                "alg": {
                  "type": "string"
                }
              }
            }
          }
        },
        "example": {
          "keys": [
            {
              "kty": "string",
              "crv": "string",
              "kid": "clxx...",
              "use": "string",
              "alg": "string"
            }
          ]
        }
      },
      "ntfOauth_GetAuthorizationServerMetadataResponse": {
        "type": "object",
        "properties": {
          "issuer": {
            "type": "string"
          },
          "authorization_endpoint": {
            "type": "string"
          },
          "token_endpoint": {
            "type": "string"
          },
          "registration_endpoint": {
            "type": "string"
          },
          "revocation_endpoint": {
            "type": "string"
          },
          "jwks_uri": {
            "type": "string"
          },
          "response_types_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "grant_types_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "code_challenge_methods_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token_endpoint_auth_methods_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "example": {
          "issuer": "string",
          "authorization_endpoint": "string",
          "token_endpoint": "string",
          "registration_endpoint": "string",
          "revocation_endpoint": "string",
          "jwks_uri": "string",
          "response_types_supported": [
            "string"
          ],
          "grant_types_supported": [
            "string"
          ],
          "code_challenge_methods_supported": [
            "string"
          ],
          "token_endpoint_auth_methods_supported": [
            "string"
          ],
          "scopes_supported": [
            "string"
          ]
        }
      },
      "ntfOauth_GetProtectedResourceMetadataResponse": {
        "type": "object",
        "properties": {
          "resource": {
            "type": "string"
          },
          "authorization_servers": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "example": {
          "resource": "string",
          "authorization_servers": [
            "string"
          ],
          "scopes_supported": [
            "string"
          ]
        }
      },
      "ntfOauth_RegisterClientResponse": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": "string"
          },
          "client_name": {
            "type": "string"
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token_endpoint_auth_method": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          },
          "client_id_issued_at": {
            "type": "integer"
          }
        },
        "example": {
          "client_id": "clxx...",
          "client_secret": "string",
          "client_name": "string",
          "redirect_uris": [
            "string"
          ],
          "grant_types": [
            "string"
          ],
          "response_types": [
            "string"
          ],
          "token_endpoint_auth_method": "string",
          "scope": "string",
          "client_id_issued_at": 1
        }
      },
      "ntfOauth_RevokeResponse": {
        "type": "object",
        "additionalProperties": false,
        "description": "Resposta JSON vazia (sucesso sem payload).",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          }
        },
        "example": {
          "success": true
        }
      },
      "ntfOauth_TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "token_type": {
            "type": "string"
          },
          "expires_in": {
            "type": "integer"
          },
          "refresh_token": {
            "type": "string"
          },
          "scope": {
            "type": "string"
          }
        },
        "example": {
          "access_token": "string",
          "token_type": "string",
          "expires_in": 1,
          "refresh_token": "string",
          "scope": "string"
        }
      },
      "ntfOauth_ListWorkspaceAppsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "clientId": {
                  "type": "string"
                },
                "redirectUris": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "createdAt": {
                  "type": "string"
                }
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": [
            {
              "id": "clxx...",
              "name": "Exemplo",
              "clientId": "clxx...",
              "redirectUris": [
                "string"
              ],
              "scopes": [
                "string"
              ],
              "createdAt": "string"
            }
          ]
        }
      },
      "ntfOauth_CreateWorkspaceAppResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "clientId": {
                "type": "string"
              },
              "clientSecret": {
                "type": "string"
              },
              "redirectUris": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": {
            "id": "clxx...",
            "name": "Exemplo",
            "clientId": "clxx...",
            "clientSecret": "string",
            "redirectUris": [
              "string"
            ],
            "scopes": [
              "string"
            ]
          }
        }
      },
      "ntfOauth_DeleteWorkspaceAppResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "deleted": {
                "type": "boolean"
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": {
            "id": "clxx...",
            "deleted": true
          }
        }
      },
      "ntfOauth_GetWorkspaceAppResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "clientId": {
                "type": "string"
              },
              "redirectUris": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": {
            "id": "clxx...",
            "name": "Exemplo",
            "clientId": "clxx...",
            "redirectUris": [
              "string"
            ],
            "scopes": [
              "string"
            ]
          }
        }
      },
      "ntfOauth_UpdateWorkspaceAppResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": {
            "id": "clxx...",
            "name": "Exemplo"
          }
        }
      },
      "ntfOauth_RotateWorkspaceAppSecretResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "clientId": {
                "type": "string"
              },
              "clientSecret": {
                "type": "string"
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": {
            "id": "clxx...",
            "clientId": "clxx...",
            "clientSecret": "string"
          }
        }
      },
      "ntfOauth_ListConnectionsResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "appId": {
                  "type": "string"
                },
                "appName": {
                  "type": "string"
                },
                "userEmail": {
                  "type": "string"
                },
                "scopes": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "createdAt": {
                  "type": "string"
                }
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": [
            {
              "id": "clxx...",
              "appId": "clxx...",
              "appName": "string",
              "userEmail": "string",
              "scopes": [
                "string"
              ],
              "createdAt": "string"
            }
          ]
        }
      },
      "ntfOauth_RevokeConnectionResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "revoked": {
                "type": "boolean"
              }
            }
          }
        },
        "example": {
          "success": true,
          "data": {
            "id": "clxx...",
            "revoked": true
          }
        }
      }
    },
    "responses": {
      "NtfOauth_Unauthorized": {
        "description": "Chave ausente, inválida ou revogada.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/NtfOauth_Error"
            },
            "example": {
              "success": false,
              "error": "Unauthorized",
              "message": "Invalid API key",
              "code": "UNAUTHORIZED"
            }
          }
        }
      },
      "NtfOauth_Forbidden": {
        "description": "Escopo ausente ou recurso fora da permissão da chave.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/NtfOauth_Error"
            },
            "example": {
              "success": false,
              "error": "Forbidden",
              "message": "Missing scope webhooks:manage",
              "code": "FORBIDDEN"
            }
          }
        }
      },
      "NtfOauth_NotFound": {
        "description": "Recurso não encontrado no workspace.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/NtfOauth_Error"
            },
            "example": {
              "success": false,
              "error": "Not Found",
              "message": "Webhook not found",
              "code": "NOT_FOUND"
            }
          }
        }
      },
      "NtfOauth_BadRequest": {
        "description": "Body inválido ou campo inesperado.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/NtfOauth_Error"
            },
            "examples": {
              "validation": {
                "value": {
                  "success": false,
                  "error": "Bad Request",
                  "message": "url must be HTTPS",
                  "code": "VALIDATION_ERROR"
                }
              },
              "unexpected_fields": {
                "value": {
                  "success": false,
                  "code": "UNEXPECTED_FIELDS"
                }
              }
            }
          }
        }
      }
    }
  }
}
