Convenções REST implementadas (L1)
Base pública de produção: https://api.aedifica.audaces-scale.com/v1.
JSON UTF-8; camelCase e formas dos schemas partilhados, sem envelope de transporte Firestore. Item: {data:resource}; documentos mantêm {document,editor,blocks,version,updatedAt}. Valores de data ISO 8601; dinheiro em euros. Cache-Control: no-store em todas as respostas.
Paginação
GET /v1/projects?limit=25&cursor=<opaco>. limit: inteiro 1–100, omissão 25. Ordenação estável por ID ascendente. O cursor é ligado à organização e recurso; não é uma credencial. Resposta {data:[…],hasMore:true,nextCursor:"…"}; no fim hasMore:false,nextCursor:null. Não há filtros, sort, expand nem cabeçalho de versão por data; parâmetros não suportados são rejeitados.
Idempotência
Todos os POST exigem Idempotency-Key (1–128 caracteres ASCII visíveis sem espaços). Âmbito por chave e organização, retenção lógica 24 horas. A transação grava o recurso e a resposta em apiIdempotency atomicamente. Pedido repetido devolve a resposta original (200 e Idempotency-Replayed: true); primeiro pedido: 201. Mesmo identificador com recurso/corpo diferente: 409 idempotency_mismatch. A ordem das chaves JSON não altera a comparação. Arrays preservam ordem. TTL físico da coleção é uma tarefa de operação, não uma garantia implementada pela aplicação.
Limites
60 pedidos/minuto/chave, janela por minuto UTC em apiRateLimits com transação Firestore. Cabeçalhos RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset (segundos Unix). Excesso: 429 + Retry-After. Corpo de criação máximo 1 MB e MIME application/json.
Erros
Sempre { "error": { "code": "validation_failed", "message": "Dados inválidos para o recurso" } }. Sem stack, corpos de pedidos ou segredos em logs/respostas de erro.
| HTTP | Código |
|---|---|
| 400 | invalid_argument, invalid_cursor, idempotency_required |
| 401 | invalid_api_key |
| 403 | insufficient_scope, role_forbidden |
| 404 | not_found |
| 405 | method_not_allowed |
| 409 | idempotency_mismatch, time_overlap |
| 413 | payload_too_large |
| 415 | unsupported_media_type |
| 422 | validation_failed, invalid_reference |
| 429 | rate_limited |
| 500 | internal |
Só GET e POST estão implementados. Não há emissão, numeração, cancelamento fiscal, pagamentos ou comunicação fiscal nesta API.