Contrato de respostas e erros da Admin API
Este ficheiro completa o contrato de resposta de todos os endpoints na Referência de endpoints. Consulte a linha do endpoint para o corpo de sucesso e as tabelas abaixo para todos os corpos de insucesso comuns ou específicos. Por predefinição, os erros usam várias estruturas de compatibilidade; os clientes podem optar por um envelope universal.
Envelope de erro estruturado opcional
Envie este cabeçalho de pedido para qualquer endpoint:
X-Error-Format: envelope
A comparação remove espaços nas extremidades e não distingue maiúsculas de minúsculas. Com esse valor exato, todas as respostas JSON com estado 400 ou superior são convertidas em:
ErrorEnvelope = {
error: {
code: string,
message: string,
details: Record<string, unknown>,
requestId: string
}
}
Exemplo de conversão de um corpo de validação predefinido:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Invalid request",
"details": {
"fields": {
"name": ["String must contain at least 1 character(s)"]
}
},
"requestId": "integration-42"
}
}
As regras de conversão são exatas:
validationErrorspassa adetails.fieldsecodepassa aVALIDATION_FAILED, mesmo quando o corpo predefinido também tinha um código de domínio.- É mantido um
codepredefinido no nível superior quando não existem campos de validação. - As outras propriedades de nível superior, exceto
error,message,validationErrorsecode, passam paradetails; por exemplo,limitda exportação de relatórios passa adetails.limit. - Um
errorde texto no nível superior passa amessage. Se não existir, é usado o valor de recurso do estado. - Os códigos de recurso são
AUTH_REQUIRED(401),PERMISSION_DENIED(403),RESOURCE_NOT_FOUND(404),CONFLICT(409),VALIDATION_FAILED(422e outros4xxnão classificados),RATE_LIMITED(429),EXTERNAL_PROVIDER_FAILED(502) eINTERNAL_ERROR(outros5xx, incluindo503). requestIdé o cabeçalho de respostaX-Request-Idexato. Um ID de pedido fornecido pelo cliente só é usado quando corresponde a[A-Za-z0-9._:-]{1,128}após remover espaços nas extremidades; caso contrário, o servidor gera um UUID.
Esta transformação não altera o estado nem os cabeçalhos não relacionados com o corpo. Também se aplica a repetições idempotentes segundo o cabeçalho X-Error-Format do pedido de repetição. As respostas de sucesso binárias permanecem binárias; os respetivos erros JSON recebem o envelope. As tabelas restantes mostram os corpos predefinidos; as regras acima produzem o outro corpo de resposta possível para cada linha.
Notação das respostas
ValidationError = {
validationErrors: Record<string, string[]>,
code?: string
}
CodedError = {
error: string,
code: string,
// a route may add fields explicitly listed below
}
PlainError = { error: string }
error e o texto da mensagem de validação são descritivos, não discriminadores programáticos estáveis. Distinga casos por code quando presente. A validação do pedido devolve 422 ValidationError; a validação de um objeto completo pode produzir { "validationErrors": {} } quando não é identificado um campo individual. JSON inválido e falhas inesperadas devolvem o 500 PlainError global abaixo.
Todos os exemplos JSON apresentam a estrutura exata do corpo. O texto apresentado como <message> é a mensagem de validação ou operação devolvida e é uma cadeia JSON, não um valor literal entre parênteses angulares.
Ordem de processamento dos pedidos
Os pedidos são processados por esta ordem:
- configuração e autenticação dos tokens de espaço de trabalho;
- política do anfitrião e limites de pedidos por token/espaço de trabalho;
- filtragem dos direitos atuais;
- para cada alteração, validação/reserva de idempotência;
- verificações de âmbito do endpoint, validação do pedido e operação solicitada.
Assim, uma alteração com um token válido, mas com âmbitos insuficientes, continua a exigir o envio de Idempotency-Key. Uma resposta concluída de alteração 403, 404, 409 ou 422 pode ser repetida para a mesma chave/pedido.
Respostas de autenticação, política e limitação de pedidos
Estas respostas podem ocorrer em qualquer endpoint /v2/admin registado antes do processamento específico do endpoint.
| Estado | Quando | Corpo exato | Cabeçalhos relevantes |
|---|---|---|---|
401 | Token do espaço de trabalho ausente, duplicado, unido por vírgulas, não Bearer, malformado, desconhecido, expirado, revogado ou inválido por outro motivo | { "error": "Unauthorized", "code": "INVALID_WORKSPACE_TOKEN" } | WWW-Authenticate: Bearer, Cache-Control: no-store |
404 | O token é válido, mas o anfitrião do espaço de trabalho não tem adminApiEnabled | { "error": "Not Found" } | Cache-Control: no-store |
429 | A quota de pedidos por token ou espaço de trabalho está esgotada | { "error": "Too many attempts. Please try again later." } | Retry-After: <seconds> |
503 | A autenticação por token do espaço de trabalho está temporariamente indisponível | { "error": "Admin API workspace-token configuration is unavailable", "code": "WORKSPACE_API_CONFIG_UNAVAILABLE" } | — |
503 | Falha na consulta da política do anfitrião ou na autorização dos direitos atuais | { "error": "Workspace authorization is temporarily unavailable", "code": "WORKSPACE_AUTHORIZATION_UNAVAILABLE" } | — |
O acesso à API está incluído em todos os planos. Desativar a definição adminApiEnabled do anfitrião do espaço de trabalho devolve 404; perder um direito de função adicional remove apenas os âmbitos afetados. A recusa de âmbito resultante usa a resposta abaixo, não um fluxo de renovação de tokens.
Âmbito, idempotência, análise, propriedade e falhas inesperadas
| Aplica-se a | Estado | Corpo exato | Cabeçalhos/notas |
|---|---|---|---|
| Todas as rotas após a autenticação | 403 | { "error": "Insufficient workspace-token scope", "code": "INSUFFICIENT_SCOPE" } | Devolvido quando falta qualquer âmbito obrigatório. |
| Cada alteração | 400 | { "error": "Idempotency-Key is required for this operation", "code": "IDEMPOTENCY_KEY_REQUIRED" } | Não foi fornecida nenhuma chave. |
| Cada alteração | 400 | { "error": "Exactly one Idempotency-Key is required", "code": "INVALID_IDEMPOTENCY_KEY" } | Cabeçalho duplicado ou unido por vírgulas. |
| Cada alteração | 400 | { "error": "Idempotency-Key must contain 1 to 255 visible characters", "code": "INVALID_IDEMPOTENCY_KEY" } | Vazio, demasiado longo ou contém um carácter de controlo. |
| Cada alteração | 409 | { "error": "Idempotency-Key was already used with a different request", "code": "IDEMPOTENCY_CONFLICT" } | Mesmo token/método/caminho/chave, URL ou corpo diferente. |
| Cada alteração | 409 | { "error": "Request is already processing", "code": "IDEMPOTENT_REQUEST_PROCESSING" } | Retry-After: 5. |
| Cada alteração | 409 | { "error": "Previous request outcome is unknown; verify its effects before attempting the operation again", "code": "IDEMPOTENCY_OUTCOME_UNKNOWN" } | A concessão de processamento anterior expirou, a ligação foi fechada ou o pedido terminou com 5xx. |
| Cada alteração | 503 | { "error": "Idempotency storage unavailable", "code": "IDEMPOTENCY_UNAVAILABLE" } | A API não consegue verificar nem guardar o registo de idempotência. |
| Qualquer endpoint com um esquema de consulta/corpo/caminho inválido | 422 | { "validationErrors": { "<field>": ["<message>"] } } | Podem existir vários campos/mensagens. Os clientes não podem fornecer cpoId; o espaço de trabalho vem sempre do token. |
| Qualquer recurso aninhado em falta ou ID de outro espaço de trabalho | 404 | { "error": "Workspace resource not found", "code": "RESOURCE_NOT_FOUND" } | Usado de forma consistente, salvo indicação em contrário numa tabela abaixo. |
| Qualquer endpoint com uma falha inesperada | 500 | { "error": "Something went wrong" } | Nas alterações, repetir a mesma chave mais tarde resulta em 409 IDEMPOTENCY_OUTCOME_UNKNOWN. |
Os IDs nos caminhos de recursos têm de ser números positivos. Um :siteId, :chargerId, :portId, :tariffId, :profileId, :assignmentId, :userId, :rfidId, :accessId, :limitId ou :localUserId não positivo ou não numérico devolve 422 ValidationError, não 400.
Erros de locais e gestão de potência
| Endpoints | Estado | Corpo exato |
|---|---|---|
| Criação/atualização de local; validação de campos do espaço de trabalho | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
DELETE /v2/admin/sites/:siteId quando o local tem dependências | 409 | { "error": "<message>", "code": "SITE_NOT_EMPTY" } |
GET /v2/admin/sites/geocode pesquisa normalizada inválida | 400 | { "error": "<message>", "code": "INVALID_GEOCODE_QUERY" } |
| O mesmo, fila limitada do fornecedor cheia | 429 | { "error": "<message>", "code": "GEOCODING_BUSY" }; inclui Retry-After quando fornecido pelo geocodificador |
| O mesmo, tempo esgotado/falha do fornecedor ou erro inesperado do geocodificador | 502 | { "error": "<message>", "code": "GEOCODING_UNAVAILABLE" }; um erro inesperado usa Address search is temporarily unavailable |
PUT /v2/admin/sites/:siteId/power-management configuração de topologia/domínio inválida | 422 | { "error": "<message>", "code": "INVALID_POWER_MANAGEMENT_CONFIGURATION" } |
| O mesmo, recusa/tempo esgotado OCPP, concorrência ou conflito de reconciliação | 409 | { "error": "<message>", "code": "POWER_MANAGEMENT_CONFLICT" } |
Erros dos carregadores
mapChargerErrors() é usado na criação/atualização do carregador, credenciais, definições de conector, listagem pública, resolução de conteúdo QR, alteração/recarregamento de configuração, início de firmware, nos quatro comandos básicos e no pedido de agendamento composto.
| Endpoints | Estado | Corpo exato |
|---|---|---|
| Qualquer operação acima com falha de validação do domínio | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Qualquer operação acima com conflito de estado, unicidade, ligação/OCPP, faturação, Tagless, conector ou prontidão | 409 | { "error": "<message>", "code": "CHARGER_CONFLICT" } |
GET /chargers/:chargerId/sessions, intervalo de tempo predefinido/explícito inválido | 422 | { "validationErrors": { "from": ["from must be before or equal to to"] } } ou { "validationErrors": { "from": ["Session range cannot exceed 90 days"] } } |
As operações de leitura simples devolvem apenas as respostas comuns 401/403/404/429/500/503 e a validação 422 da consulta/caminho. A eliminação do carregador pode devolver o 500 PlainError comum se falhar sem uma resposta de erro mais específica.
Erros dos relatórios
| Endpoints | Estado | Corpo exato |
|---|---|---|
Intervalo de dados/exportação em que from >= to | 422 | { "validationErrors": { "range": ["from must be earlier than to"] } } |
| Intervalo de dados/exportação superior a 90 dias | 422 | { "validationErrors": { "range": ["Report ranges cannot exceed 90 days"] } } |
| Cursor opaco inválido de dados/medições | 422 | { "validationErrors": { "cursor": ["<message>"] } } |
GET /reports/export, o resultado excede 2 000 linhas | 422 | { "error": "<message>", "code": "REPORT_EXPORT_ROW_LIMIT", "limit": 2000 } |
POST /reports/send, sem agendamento guardado | 409 | { "error": "A workspace report schedule must be saved before sending", "code": "REPORT_SCHEDULE_REQUIRED" } |
| O mesmo, serviço de email rejeita/falha | 502 | { "error": "Report delivery failed", "code": "REPORT_DELIVERY_FAILED" } |
| Recurso de agendamento/medições pertencente ao espaço de trabalho ausente | 404 | corpo comum RESOURCE_NOT_FOUND |
A exportação bem-sucedida é binária; todos os erros de exportação continuam a ser JSON.
Erros das tarifas
| Endpoints | Estado | Corpo exato |
|---|---|---|
| Validação de domínio de criação/atualização/componentes/preços de mercado/atribuição | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Conflito de estado/dependência/unicidade na eliminação ou atribuição de tarifa | 409 | { "error": "<message>", "code": "TARIFF_CONFLICT" } |
| Tarifa, zona de ofertas, carregador, conector, atribuição de tarifa ou outro recurso aninhado não pertencente ao proprietário | 404 | corpo comum RESOURCE_NOT_FOUND |
Erros dos perfis de carregamento
| Endpoints | Estado | Corpo exato |
|---|---|---|
| Validação de domínio de criação/atualização/agendamento/atribuição | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| O perfil é referenciado por uma utilização protegida | 409 | { "error": "<message>", "code": "CHARGING_PROFILE_IN_USE" } |
| Conflito de sincronização OCPP, atribuição, concorrência ou outro conflito de perfil | 409 | { "error": "<message>", "code": "CHARGING_PROFILE_CONFLICT" } |
| Perfil, carregador, conector, atribuição ou outro recurso aninhado não pertencente ao proprietário | 404 | corpo comum RESOURCE_NOT_FOUND |
Erros do domínio de utilizadores
Os erros de validação de utilizadores que identificam um campo usam ValidationError e code; os restantes usam CodedError. Todos os casos de recursos em falta usam a resposta comum RESOURCE_NOT_FOUND, que não revela a existência de recursos.
| Estado | Código(s) | Corpo |
|---|---|---|
400 | INVALID_USER_CURSOR | { "validationErrors": { "cursor": ["The user-list cursor is invalid for the selected status"] }, "code": "INVALID_USER_CURSOR" } |
409 | USER_ALREADY_EXISTS, CUSTOMER_CONTRACT_MISSING, INVITATION_EMAIL_IN_USE, RFID_ALREADY_EXISTS, ACCESS_ALREADY_EXISTS, ACCESS_ALL_ALREADY_EXISTS, LIMIT_ALREADY_EXISTS, LOCAL_USER_ALREADY_EXISTS, PROTECTED_WORKSPACE_USER, TAGLESS_USER_PROTECTED, USER_RELATED_DATA | { "error": "<message>", "code": "<listed code>" } |
422 | INVALID_EMAIL, INVALID_RFID, INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE | { "validationErrors": { "<field>": ["<message>"] }, "code": "<listed code>" } |
422 | NO_CHARGERS_AVAILABLE | { "error": "No chargers are available", "code": "NO_CHARGERS_AVAILABLE" } |
429 | INVITATION_RESEND_THROTTLED | { "error": "Invitation resend is temporarily unavailable", "code": "INVITATION_RESEND_THROTTLED" }; inclui Retry-After |
503 | USER_CURSOR_UNAVAILABLE | { "error": "User pagination is temporarily unavailable", "code": "USER_CURSOR_UNAVAILABLE" } |
404 | RESOURCE_NOT_FOUND | { "error": "Workspace resource not found", "code": "RESOURCE_NOT_FOUND" } |
POST /users/invitations também pode devolver o 403 INSUFFICIENT_SCOPE comum após analisar o corpo se faltar users:access, ou se tiver sido fornecido RFID e faltar users:rfid. Os endpoints de utilizadores locais indicam todos os âmbitos obrigatórios na Referência de endpoints.
Os códigos de erro de utilizador aplicam-se da seguinte forma:
| Família de endpoints | Códigos do domínio de utilizadores diferentes de 404, além das respostas comuns |
|---|---|
GET /users | INVALID_USER_CURSOR (400), USER_CURSOR_UNAVAILABLE (503) |
POST /users | USER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409) |
PATCH /users/:userId | TAGLESS_USER_PROTECTED (409) |
DELETE /users/:userId | TAGLESS_USER_PROTECTED, PROTECTED_WORKSPACE_USER, USER_RELATED_DATA (409) |
| Leitura de detalhes do utilizador, veículos, RFID/acesso/limites | nenhum código de domínio diferente de 404 |
| Criar RFID | CUSTOMER_CONTRACT_MISSING, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_RFID (422) |
| Atualizar/eliminar RFID | TAGLESS_USER_PROTECTED (409) |
| Substituição de acesso | TAGLESS_USER_PROTECTED (409); NO_CHARGERS_AVAILABLE (422) |
| Revogação de acesso | TAGLESS_USER_PROTECTED (409) |
| Criar/atualizar limite | TAGLESS_USER_PROTECTED, LIMIT_ALREADY_EXISTS (409); INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE (422) |
| Eliminar limite | TAGLESS_USER_PROTECTED (409) |
| Criar convite do espaço de trabalho | CUSTOMER_CONTRACT_MISSING, INVITATION_EMAIL_IN_USE, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL/INVALID_RFID (422); INVITATION_RESEND_THROTTLED (429) quando se aplica o período de espera de envio |
| Reenviar convite do espaço de trabalho | INVALID_EMAIL (422), INVITATION_RESEND_THROTTLED (429) |
| Cancelar convite do espaço de trabalho | INVALID_EMAIL (422) |
| Criação de utilizador local de carregador para cliente existente | LOCAL_USER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409) |
| Convite de utilizador local de carregador | LOCAL_USER_ALREADY_EXISTS, INVITATION_EMAIL_IN_USE, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL (422); INVITATION_RESEND_THROTTLED (429) quando se aplica o período de espera de envio |
| Cancelar convite de utilizador local | INVALID_EMAIL (422) |
| Atualizar/eliminar utilizador local | TAGLESS_USER_PROTECTED (409) |
Todos os resultados de propriedade e recursos em falta nestas famílias, incluindo um email não registado em POST /users, usam o corpo comum 404 RESOURCE_NOT_FOUND.
Respostas sem corpo e de repetição
Uma resposta 204 bem-sucedida não tem corpo. Isto aplica-se a todas as eliminações documentadas que indicam 204 empty. Uma repetição idempotente concluída define Idempotency-Replayed: true e usa o estado/corpo guardado; para 204, a resposta HTTP continua sem corpo. A API nunca devolve um objeto JSON de sucesso para uma operação 204 documentada.