API Keys

Endpoints administrativos da WebApiAlcance para gerenciar API Keys - as credenciais que autenticam o acesso à própria API. Cobrem geração de novas chaves, listagem geral (restrita a perfil administrador/diretoria), listagem das chaves do usuário logado, detalhamento por ID, atualização, exclusão e o gerenciamento dos escopos associados a cada chave.

Domínio administrativo - nunca exponha ao MCP

Este é um domínio de gestão de credenciais. Ele governa a emissão e a revogação das próprias chaves de acesso à API e NUNCA deve ser exposto ao gateway MCP nem a clientes de IA. Expor estes endpoints permitiria a um cliente autônomo criar chaves, escalar os próprios escopos e apagar credenciais - uma falha de segurança grave. Mantenha api_keys:read e api_keys:write fora de qualquer API Key emitida para o MCP.

Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs.

Base path

/api/v1/api-keys

A URL completa em produção é https://api.contabilidadealcance.com.br/api/v1/api-keys.

Escopos necessários

  • api_keys:read - listagem, detalhamento e leitura de escopos
  • api_keys:write - geração, atualização, exclusão e substituição de escopos

O escopo é derivado da rota, mas com uma pegadinha de normalização: o prefixo da URL é /api-keys (com hífen), porém o recurso de escopo é api_keys (com underscore) - o hífen do path vira underscore no código do escopo. A ação segue o método HTTP: read para GET e write para POST/PUT/PATCH/DELETE. Portanto os escopos corretos são api_keys:read e api_keys:write, não api-keys:read.

Controles de privilégio

Além dos escopos, alguns endpoints aplicam regras extras: GET /api-keys/ exige perfil administrador ou diretoria (require_perfil); apenas esses dois perfis podem conceder escopo_global; e um usuário funcionario não pode criar/atribuir a uma chave escopos além dos seus próprios (princípio do menor privilégio). O acesso a uma chave específica também exige propriedade (require_api_key_ownership): administrador/diretoria acessam qualquer chave, funcionario só as próprias (a chave inexistente ainda responde 404, avaliado antes da checagem de perfil).

Endpoints

POST /api-keys/

Gera uma nova API Key para o usuário logado. Retorna a chave criada com o segredo em texto puro no campo api_key - exibido uma única vez. escopo_global = true só é aceito de perfil administrador/diretoria (403 caso contrário) e um usuário funcionario só pode informar scope_ids que já possua (escopos além dos seus geram 403).

Parâmetros

Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (ApiKeyCreate): nome (obrigatório), expiracao (default "nunca"), escopo_global (default false) e scope_ids (default []).

Request

{
  "nome": "Integração DCTFWeb",
  "expiracao": "nunca",
  "escopo_global": false,
  "scope_ids": [3, 8]
}

Response 200 OK

{
  "success": true,
  "message": "API Key gerada com sucesso! Guarde a chave, ela nao sera exibida novamente.",
  "data": {
    "id": 42,
    "usuario_id": 7,
    "nome": "Integração DCTFWeb",
    "key_prefix": "ak_live_9f3b",
    "expiracao": "nunca",
    "data_expiracao": null,
    "ativo": true,
    "escopo_global": false,
    "criado_em": "2026-07-03T09:15:00-03:00",
    "ultimo_uso": null,
    "scopes": [],
    "api_key": "ak_live_9f3b8c1d2e4f5a6b7c8d9e0f1a2b3c4d"
  }
}

O segredo aparece só uma vez

O campo api_key (o segredo em texto puro) é retornado exclusivamente nesta resposta de criação. Ele não é armazenado de forma recuperável e nunca volta a ser exibido - nem no GET /me, nem no GET /{api_key_id}, que só devolvem o key_prefix. Copie e guarde o valor com segurança no momento da criação; se perder, a única saída é revogar a chave e gerar outra.

Escopo: api_keys:write

GET /api-keys/

Lista todas as API Keys de todos os usuários. Endpoint restrito a perfil administrador ou diretoria (require_perfil); um usuário funcionario recebe 403. O segredo em texto puro nunca é incluído.

Parâmetros

Este endpoint não recebe parâmetros de rota ou query. A resposta traz um array de ApiKeyRead.

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "API Keys listadas com sucesso!",
  "data": [
    {
      "id": 42,
      "usuario_id": 7,
      "nome": "Integração DCTFWeb",
      "key_prefix": "ak_live_9f3b",
      "expiracao": "nunca",
      "data_expiracao": null,
      "ativo": true,
      "escopo_global": false,
      "criado_em": "2026-07-03T09:15:00-03:00",
      "ultimo_uso": null,
      "scopes": []
    }
  ]
}

Escopo: api_keys:read (além de perfil administrador ou diretoria)

GET /api-keys/me

Lista as API Keys do usuário logado. Lista vazia é um estado válido - retorna 200 OK com data: [].

Parâmetros

Este endpoint não recebe parâmetros de rota ou query. A resposta traz um array de ApiKeyRead.

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Suas API Keys listadas com sucesso!",
  "data": [
    {
      "id": 42,
      "usuario_id": 7,
      "nome": "Integração DCTFWeb",
      "key_prefix": "ak_live_9f3b",
      "expiracao": "nunca",
      "data_expiracao": null,
      "ativo": true,
      "escopo_global": false,
      "criado_em": "2026-07-03T09:15:00-03:00",
      "ultimo_uso": "2026-07-05T14:22:00-03:00",
      "scopes": []
    }
  ]
}

Escopo: api_keys:read

GET /api-keys/{api_key_id}

Detalha uma API Key pelo ID inteiro. Exige que a chave pertença ao usuário logado, salvo perfil administrador/diretoria, que acessa qualquer chave (require_api_key_ownership). Quando não encontrada, retorna 404 Not Found - avaliado antes da checagem de perfil.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
api_key_idintpathsimID interno da chave

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "API Key encontrada!",
  "data": {
    "id": 42,
    "usuario_id": 7,
    "nome": "Integração DCTFWeb",
    "key_prefix": "ak_live_9f3b",
    "expiracao": "nunca",
    "data_expiracao": null,
    "ativo": true,
    "escopo_global": false,
    "criado_em": "2026-07-03T09:15:00-03:00",
    "ultimo_uso": "2026-07-05T14:22:00-03:00",
    "scopes": []
  }
}

Escopo: api_keys:read

PUT /api-keys/{api_key_id}

Atualiza uma API Key existente. O body é um ApiKeyUpdate com campos parciais (exclude_unset) - somente o que vier preenchido é alterado. Permite renomear (nome) e ativar/desativar (ativo) a chave. Exige propriedade da chave (require_api_key_ownership), salvo perfil administrador/diretoria.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
api_key_idintpathsimID da chave

Request (ApiKeyUpdate - todos os campos opcionais)

{
  "nome": "Integração DCTFWeb (produção)",
  "ativo": false
}

Response 200 OK

{
  "success": true,
  "message": "API Key atualizada com sucesso!",
  "data": {
    "id": 42,
    "usuario_id": 7,
    "nome": "Integração DCTFWeb (produção)",
    "key_prefix": "ak_live_9f3b",
    "expiracao": "nunca",
    "data_expiracao": null,
    "ativo": false,
    "escopo_global": false,
    "criado_em": "2026-07-03T09:15:00-03:00",
    "ultimo_uso": "2026-07-05T14:22:00-03:00",
    "scopes": []
  }
}

Revogar sem apagar

Para desativar uma chave sem removê-la da base, use ativo: false. É a forma recomendada de revogar uma credencial preservando o histórico de auditoria.

Escopo: api_keys:write

DELETE /api-keys/{api_key_id}

Remove permanentemente uma API Key. Exige propriedade da chave (require_api_key_ownership), salvo perfil administrador/diretoria.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
api_key_idintpathsimID da chave

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "API Key removida com sucesso!",
  "data": null
}

Escopo: api_keys:write

GET /api-keys/{api_key_id}/scopes

Lista os escopos associados a uma API Key, junto do indicador escopo_global. Exige propriedade da chave (require_api_key_ownership), salvo perfil administrador/diretoria.

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
api_key_idintpathsimID da chave

Request

Sem corpo de requisição.

Response 200 OK

{
  "success": true,
  "message": "Escopos da API Key listados com sucesso.",
  "data": {
    "escopo_global": false,
    "scopes": [
      { "id": 3, "codigo": "customers:read", "recurso": "customers", "acao": "read" },
      { "id": 8, "codigo": "lembretes:write", "recurso": "lembretes", "acao": "write" }
    ]
  }
}

Escopo: api_keys:read

PUT /api-keys/{api_key_id}/scopes

Substitui (não incrementa) a lista de escopos de uma API Key numa única transação atômica, junto com a flag escopo_global. Exige propriedade da chave, salvo perfil administrador/diretoria. escopo_global = true só é aceito de perfil administrador/diretoria e um usuário funcionario só pode atribuir scope_ids que já possua (escopos além dos seus geram 403).

Parâmetros

ParâmetroTipoLocalObrigatórioDescrição
api_key_idintpathsimID da chave

Corpo da requisição: ScopeAssignRequest com escopo_global (bool) e scope_ids (lista completa que substitui a anterior).

Request

{
  "escopo_global": false,
  "scope_ids": [3, 8]
}

Response 200 OK

{
  "success": true,
  "message": "Escopos da API Key atualizados com sucesso.",
  "data": {
    "escopo_global": false,
    "scopes": [
      { "id": 3, "codigo": "customers:read", "recurso": "customers", "acao": "read" },
      { "id": 8, "codigo": "lembretes:write", "recurso": "lembretes", "acao": "write" }
    ]
  }
}

Escopo: api_keys:write

Schemas

ApiKeyCreate

CampoTipoObrigatórioObservações
nomestrsimNome descritivo da chave (identifica a integração).
expiracaostrnãoPolítica de expiração. Default "nunca".
escopo_globalboolnãoConcede acesso global. Default false. Somente perfil administrador/diretoria pode definir true.
scope_idslist[int]nãoIDs dos escopos concedidos. Default []. Limitado aos escopos do próprio usuário.

ApiKeyUpdate

Todos os campos são opcionais; apenas os enviados são atualizados.

CampoTipoObservações
nomestrNovo nome descritivo da chave.
ativoboolAtiva (true) ou revoga (false) a chave.

ApiKeyRead

Objeto de leitura devolvido nas listagens e no detalhamento. Nunca contém o segredo em texto puro.

CampoTipoNotas
idintIdentificador da chave.
usuario_idintUsuário dono da chave.
nomestrNome descritivo.
key_prefixstrPrefixo público da chave (para identificação; não é o segredo).
expiracaostrPolítica de expiração (ex.: "nunca").
data_expiracaodatetime | nullData de expiração calculada, quando houver.
ativoboolSe a chave está ativa.
escopo_globalboolSe possui acesso global. Default false.
criado_emdatetime | nullTimestamp de criação.
ultimo_usodatetime | nullÚltimo uso registrado (null se nunca usada).
scopeslist[ScopeRead]Escopos associados à chave.

ApiKeyCreatedResponse

Estende ApiKeyRead com um único campo adicional, retornado apenas na criação:

CampoTipoNotas
api_keystrO segredo em texto puro. Exibido uma só vez; não é recuperável depois.

ScopeRead

Usado dentro de ApiKeyRead.scopes e nas respostas de escopos.

CampoTipoNotas
idintIdentificador do escopo.
codigostrCódigo canônico (ex.: customers:read).
recursostrRecurso (ex.: customers, api_keys).
acaostrAção (read ou write).
descricaostr | nullDescrição legível do escopo.
tag_openapistr | nullTag OpenAPI para agrupamento em telas de UI.
criado_emdatetime | nullTimestamp de criação do escopo.

ScopeAssignRequest

Payload de PUT /api-keys/{api_key_id}/scopes (o mesmo formato é usado ao atribuir escopos a usuários).

CampoTipoObservações
escopo_globalboolDefault false. Somente perfil administrador/diretoria pode definir true.
scope_idslist[int]Conjunto completo de escopos (substitui o anterior). Default [].

Notas

Nunca exponha ao gateway MCP

Reforçando: os endpoints de API Keys são administrativos e permitem escalada de privilégios (criar chaves, ampliar escopos, revogar credenciais). Jamais inclua api_keys:read ou api_keys:write numa API Key destinada ao MCP ou a clientes de IA.

Guarde o segredo na criação

O segredo (api_key) só aparece na resposta do POST /api-keys/. Não há endpoint para recuperá-lo. Perdeu? Revogue (PUT com ativo: false) ou apague (DELETE) e gere uma nova.

  • Toda resposta segue o envelope { success, message, data } (ou { success: false, message, details } em erro).
  • GET /api-keys/me é declarado antes da rota dinâmica GET /api-keys/{api_key_id}, então me é resolvido como rota estática (e não interpretado como um api_key_id).
  • O PUT /api-keys/{api_key_id}/scopes substitui o conjunto inteiro de escopos - para adicionar um escopo, envie a lista completa desejada, não apenas o novo item.
  • A gestão de escopos disponíveis vive no domínio Scopes; aqui apenas os associamos a uma chave.