Respostas e erros

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:

  • validationErrors passa a details.fields e code passa a VALIDATION_FAILED, mesmo quando o corpo predefinido também tinha um código de domínio.
  • É mantido um code predefinido no nível superior quando não existem campos de validação.
  • As outras propriedades de nível superior, exceto error, message, validationErrors e code, passam para details; por exemplo, limit da exportação de relatórios passa a details.limit.
  • Um error de texto no nível superior passa a message. 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 (422 e outros 4xx não classificados), RATE_LIMITED (429), EXTERNAL_PROVIDER_FAILED (502) e INTERNAL_ERROR (outros 5xx, incluindo 503).
  • requestId é o cabeçalho de resposta X-Request-Id exato. 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:

  1. configuração e autenticação dos tokens de espaço de trabalho;
  2. política do anfitrião e limites de pedidos por token/espaço de trabalho;
  3. filtragem dos direitos atuais;
  4. para cada alteração, validação/reserva de idempotência;
  5. 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.

EstadoQuandoCorpo exatoCabeçalhos relevantes
401Token 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
404O token é válido, mas o anfitrião do espaço de trabalho não tem adminApiEnabled{ "error": "Not Found" }Cache-Control: no-store
429A quota de pedidos por token ou espaço de trabalho está esgotada{ "error": "Too many attempts. Please try again later." }Retry-After: <seconds>
503A 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" }—
503Falha 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 aEstadoCorpo exatoCabeçalhos/notas
Todas as rotas após a autenticação403{ "error": "Insufficient workspace-token scope", "code": "INSUFFICIENT_SCOPE" }Devolvido quando falta qualquer âmbito obrigatório.
Cada alteração400{ "error": "Idempotency-Key is required for this operation", "code": "IDEMPOTENCY_KEY_REQUIRED" }Não foi fornecida nenhuma chave.
Cada alteração400{ "error": "Exactly one Idempotency-Key is required", "code": "INVALID_IDEMPOTENCY_KEY" }Cabeçalho duplicado ou unido por vírgulas.
Cada alteração400{ "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ção409{ "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ção409{ "error": "Request is already processing", "code": "IDEMPOTENT_REQUEST_PROCESSING" }Retry-After: 5.
Cada alteração409{ "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ção503{ "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álido422{ "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 trabalho404{ "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 inesperada500{ "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

EndpointsEstadoCorpo exato
Criação/atualização de local; validação de campos do espaço de trabalho422{ "validationErrors": { "<field>": ["<message>"] } }
DELETE /v2/admin/sites/:siteId quando o local tem dependências409{ "error": "<message>", "code": "SITE_NOT_EMPTY" }
GET /v2/admin/sites/geocode pesquisa normalizada inválida400{ "error": "<message>", "code": "INVALID_GEOCODE_QUERY" }
O mesmo, fila limitada do fornecedor cheia429{ "error": "<message>", "code": "GEOCODING_BUSY" }; inclui Retry-After quando fornecido pelo geocodificador
O mesmo, tempo esgotado/falha do fornecedor ou erro inesperado do geocodificador502{ "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álida422{ "error": "<message>", "code": "INVALID_POWER_MANAGEMENT_CONFIGURATION" }
O mesmo, recusa/tempo esgotado OCPP, concorrência ou conflito de reconciliação409{ "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.

EndpointsEstadoCorpo exato
Qualquer operação acima com falha de validação do domínio422{ "validationErrors": { "<field>": ["<message>"] } }
Qualquer operação acima com conflito de estado, unicidade, ligação/OCPP, faturação, Tagless, conector ou prontidão409{ "error": "<message>", "code": "CHARGER_CONFLICT" }
GET /chargers/:chargerId/sessions, intervalo de tempo predefinido/explícito inválido422{ "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

EndpointsEstadoCorpo exato
Intervalo de dados/exportação em que from >= to422{ "validationErrors": { "range": ["from must be earlier than to"] } }
Intervalo de dados/exportação superior a 90 dias422{ "validationErrors": { "range": ["Report ranges cannot exceed 90 days"] } }
Cursor opaco inválido de dados/medições422{ "validationErrors": { "cursor": ["<message>"] } }
GET /reports/export, o resultado excede 2 000 linhas422{ "error": "<message>", "code": "REPORT_EXPORT_ROW_LIMIT", "limit": 2000 }
POST /reports/send, sem agendamento guardado409{ "error": "A workspace report schedule must be saved before sending", "code": "REPORT_SCHEDULE_REQUIRED" }
O mesmo, serviço de email rejeita/falha502{ "error": "Report delivery failed", "code": "REPORT_DELIVERY_FAILED" }
Recurso de agendamento/medições pertencente ao espaço de trabalho ausente404corpo comum RESOURCE_NOT_FOUND

A exportação bem-sucedida é binária; todos os erros de exportação continuam a ser JSON.

Erros das tarifas

EndpointsEstadoCorpo exato
Validação de domínio de criação/atualização/componentes/preços de mercado/atribuição422{ "validationErrors": { "<field>": ["<message>"] } }
Conflito de estado/dependência/unicidade na eliminação ou atribuição de tarifa409{ "error": "<message>", "code": "TARIFF_CONFLICT" }
Tarifa, zona de ofertas, carregador, conector, atribuição de tarifa ou outro recurso aninhado não pertencente ao proprietário404corpo comum RESOURCE_NOT_FOUND

Erros dos perfis de carregamento

EndpointsEstadoCorpo exato
Validação de domínio de criação/atualização/agendamento/atribuição422{ "validationErrors": { "<field>": ["<message>"] } }
O perfil é referenciado por uma utilização protegida409{ "error": "<message>", "code": "CHARGING_PROFILE_IN_USE" }
Conflito de sincronização OCPP, atribuição, concorrência ou outro conflito de perfil409{ "error": "<message>", "code": "CHARGING_PROFILE_CONFLICT" }
Perfil, carregador, conector, atribuição ou outro recurso aninhado não pertencente ao proprietário404corpo 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.

EstadoCódigo(s)Corpo
400INVALID_USER_CURSOR{ "validationErrors": { "cursor": ["The user-list cursor is invalid for the selected status"] }, "code": "INVALID_USER_CURSOR" }
409USER_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>" }
422INVALID_EMAIL, INVALID_RFID, INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE{ "validationErrors": { "<field>": ["<message>"] }, "code": "<listed code>" }
422NO_CHARGERS_AVAILABLE{ "error": "No chargers are available", "code": "NO_CHARGERS_AVAILABLE" }
429INVITATION_RESEND_THROTTLED{ "error": "Invitation resend is temporarily unavailable", "code": "INVITATION_RESEND_THROTTLED" }; inclui Retry-After
503USER_CURSOR_UNAVAILABLE{ "error": "User pagination is temporarily unavailable", "code": "USER_CURSOR_UNAVAILABLE" }
404RESOURCE_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 endpointsCódigos do domínio de utilizadores diferentes de 404, além das respostas comuns
GET /usersINVALID_USER_CURSOR (400), USER_CURSOR_UNAVAILABLE (503)
POST /usersUSER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409)
PATCH /users/:userIdTAGLESS_USER_PROTECTED (409)
DELETE /users/:userIdTAGLESS_USER_PROTECTED, PROTECTED_WORKSPACE_USER, USER_RELATED_DATA (409)
Leitura de detalhes do utilizador, veículos, RFID/acesso/limitesnenhum código de domínio diferente de 404
Criar RFIDCUSTOMER_CONTRACT_MISSING, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_RFID (422)
Atualizar/eliminar RFIDTAGLESS_USER_PROTECTED (409)
Substituição de acessoTAGLESS_USER_PROTECTED (409); NO_CHARGERS_AVAILABLE (422)
Revogação de acessoTAGLESS_USER_PROTECTED (409)
Criar/atualizar limiteTAGLESS_USER_PROTECTED, LIMIT_ALREADY_EXISTS (409); INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE (422)
Eliminar limiteTAGLESS_USER_PROTECTED (409)
Criar convite do espaço de trabalhoCUSTOMER_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 trabalhoINVALID_EMAIL (422), INVITATION_RESEND_THROTTLED (429)
Cancelar convite do espaço de trabalhoINVALID_EMAIL (422)
Criação de utilizador local de carregador para cliente existenteLOCAL_USER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409)
Convite de utilizador local de carregadorLOCAL_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 localINVALID_EMAIL (422)
Atualizar/eliminar utilizador localTAGLESS_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.