Contratto di risposte ed errori dell’API di amministrazione
Questo file completa il contratto delle risposte per ogni endpoint in Riferimento degli endpoint. Leggi la riga dell'endpoint per il corpo di successo e le tabelle seguenti per tutti i corpi di errore comuni o specifici dell'endpoint. Per impostazione predefinita, gli errori usano diverse strutture di compatibilità; i chiamanti possono scegliere un'unica struttura universale.
Struttura di errore facoltativa
Invia questa intestazione di richiesta a qualsiasi endpoint:
X-Error-Format: envelope
Il confronto del valore ignora gli spazi iniziali e finali e non distingue tra maiuscole e minuscole. Con quel valore esatto, ogni risposta JSON con stato pari o superiore a 400 viene convertita in:
ErrorEnvelope = {
error: {
code: string,
message: string,
details: Record<string, unknown>,
requestId: string
}
}
Esempio di conversione di un corpo di validazione predefinito:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Invalid request",
"details": {
"fields": {
"name": ["String must contain at least 1 character(s)"]
}
},
"requestId": "integration-42"
}
}
Le regole di conversione sono esatte:
validationErrorsdiventadetails.fieldsecodediventaVALIDATION_FAILED, anche quando il corpo predefinito conteneva già un codice di dominio.- Il valore
codepredefinito al livello principale viene mantenuto quando non sono presenti campi di validazione. - Le altre proprietà di primo livello, escluse
error,message,validationErrorsecode, vengono spostate indetails; ad esempio, l'esportazione dei reportlimitdiventadetails.limit. - Un campo
errordi tipo stringa al livello principale diventamessage. Se non esiste, viene usato il messaggio predefinito per lo stato. - I codici di ripiego sono
AUTH_REQUIRED(401),PERMISSION_DENIED(403),RESOURCE_NOT_FOUND(404),CONFLICT(409),VALIDATION_FAILED(422e altri4xxnon classificati),RATE_LIMITED(429),EXTERNAL_PROVIDER_FAILED(502) eINTERNAL_ERROR(altri5xx, incluso503). requestIdè l'esatta intestazione di rispostaX-Request-Id. Un ID di richiesta fornito dal chiamante viene usato solo se, dopo la rimozione degli spazi iniziali e finali, corrisponde a[A-Za-z0-9._:-]{1,128}; altrimenti il server genera un UUID.
Questa trasformazione non modifica lo stato né le intestazioni non relative al corpo. Si applica anche alle riproduzioni idempotenti in base all'intestazione X-Error-Format della richiesta di riproduzione. Le risposte binarie di successo rimangono binarie; i loro errori JSON vengono racchiusi nella struttura. Le tabelle rimanenti mostrano i corpi predefiniti; applicando le regole precedenti si ottiene l'altro possibile corpo di risposta per ogni riga.
Notazione delle risposte
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 il testo dei messaggi di convalida sono descrittivi, non discriminatori programmatici stabili. Basa le diramazioni su code, se presente. La convalida delle richieste restituisce 422 ValidationError; la convalida di un intero oggetto può produrre { "validationErrors": {} } quando non viene identificato un singolo campo. JSON non valido ed errori imprevisti restituiscono il 500 PlainError globale mostrato di seguito.
Tutti gli esempi JSON mostrano le strutture esatte del corpo. Il testo rappresentato da <message> è il messaggio di validazione o dell’operazione restituito ed è una stringa JSON, non un valore letterale tra parentesi angolari.
Ordine di elaborazione delle richieste
Le richieste vengono elaborate in questo ordine:
- configurazione e autenticazione dei token dello spazio di lavoro;
- criteri dell'host e limiti di frequenza del token/spazio di lavoro;
- filtro delle abilitazioni correnti;
- per ogni operazione di modifica, convalida/acquisizione dell'idempotenza;
- controlli degli ambiti dell'endpoint, convalida della richiesta e operazione richiesta.
Di conseguenza, anche una mutazione con un token valido ma con ambiti insufficienti deve inviare Idempotency-Key. Una risposta completata a una mutazione 403, 404, 409 o 422 può essere ripetuta per la stessa chiave e richiesta.
Risposte di autenticazione, criteri e limitazione delle richieste
Queste risposte possono verificarsi su ogni endpoint /v2/admin registrato prima dell'elaborazione specifica dell'endpoint.
| Stato | Quando | Corpo esatto | Intestazioni pertinenti |
|---|---|---|---|
401 | Token dello spazio di lavoro mancante, duplicato, unito con virgole, non Bearer, con formato errato, sconosciuto, scaduto, revocato o comunque non valido | { "error": "Unauthorized", "code": "INVALID_WORKSPACE_TOKEN" } | WWW-Authenticate: Bearer, Cache-Control: no-store |
404 | Il token è valido, ma l'host del suo spazio di lavoro non dispone di adminApiEnabled | { "error": "Not Found" } | Cache-Control: no-store |
429 | La quota delle richieste per token o per spazio di lavoro è esaurita | { "error": "Too many attempts. Please try again later." } | Retry-After: <seconds> |
503 | L'autenticazione con token dello spazio di lavoro è temporaneamente indisponibile | { "error": "Admin API workspace-token configuration is unavailable", "code": "WORKSPACE_API_CONFIG_UNAVAILABLE" } | — |
503 | La ricerca dei criteri dell'host o l'autorizzazione delle abilitazioni correnti non riesce | { "error": "Workspace authorization is temporarily unavailable", "code": "WORKSPACE_AUTHORIZATION_UNAVAILABLE" } | — |
L’accesso API è incluso in ogni piano. Disabilitare l’impostazione adminApiEnabled dell’host dello spazio di lavoro restituisce 404; perdere un diritto aggiuntivo a una funzione rimuove solo gli ambiti interessati. Il conseguente rifiuto dell’ambito usa la risposta seguente, non una procedura di aggiornamento del token.
Errori relativi ad ambiti, idempotenza, analisi, proprietà ed errori imprevisti
| Si applica a | Stato | Corpo esatto | Intestazioni/note |
|---|---|---|---|
| Ogni percorso dopo l’autenticazione | 403 | { "error": "Insufficient workspace-token scope", "code": "INSUFFICIENT_SCOPE" } | Restituito quando manca un qualsiasi ambito richiesto. |
| Ogni mutazione | 400 | { "error": "Idempotency-Key is required for this operation", "code": "IDEMPOTENCY_KEY_REQUIRED" } | Nessuna chiave fornita. |
| Ogni mutazione | 400 | { "error": "Exactly one Idempotency-Key is required", "code": "INVALID_IDEMPOTENCY_KEY" } | Intestazione duplicata o valori uniti da virgole. |
| Ogni mutazione | 400 | { "error": "Idempotency-Key must contain 1 to 255 visible characters", "code": "INVALID_IDEMPOTENCY_KEY" } | Vuoto, troppo lungo o contenente un carattere di controllo. |
| Ogni mutazione | 409 | { "error": "Idempotency-Key was already used with a different request", "code": "IDEMPOTENCY_CONFLICT" } | Stesso token/metodo/percorso/chiave, URL o corpo diverso. |
| Ogni mutazione | 409 | { "error": "Request is already processing", "code": "IDEMPOTENT_REQUEST_PROCESSING" } | Retry-After: 5. |
| Ogni mutazione | 409 | { "error": "Previous request outcome is unknown; verify its effects before attempting the operation again", "code": "IDEMPOTENCY_OUTCOME_UNKNOWN" } | Il periodo di riserva dell'elaborazione precedente è scaduto, la connessione si è chiusa oppure la richiesta si è conclusa con 5xx. |
| Ogni mutazione | 503 | { "error": "Idempotency storage unavailable", "code": "IDEMPOTENCY_UNAVAILABLE" } | L'API non può controllare o salvare la registrazione di idempotenza. |
| Qualsiasi endpoint con schema di query, corpo o percorso non valido | 422 | { "validationErrors": { "<field>": ["<message>"] } } | Possono essere presenti più campi/messaggi. I chiamanti non possono fornire cpoId; lo spazio di lavoro deriva sempre dal token. |
| Qualsiasi risorsa annidata mancante nello spazio di lavoro o ID di un altro spazio di lavoro | 404 | { "error": "Workspace resource not found", "code": "RESOURCE_NOT_FOUND" } | Usato in modo coerente, salvo diversa indicazione in una tabella seguente. |
| Qualsiasi endpoint con un errore imprevisto | 500 | { "error": "Something went wrong" } | Per le operazioni di modifica, un nuovo tentativo successivo con la stessa chiave restituisce 409 IDEMPOTENCY_OUTCOME_UNKNOWN. |
Gli ID delle risorse nel percorso devono essere numeri positivi. Un valore :siteId, :chargerId, :portId, :tariffId, :profileId, :assignmentId, :userId, :rfidId, :accessId, :limitId o :localUserId non positivo o non numerico restituisce 422 ValidationError, non 400.
Errori dei siti e della gestione della potenza
| Endpoint | Stato | Corpo esatto |
|---|---|---|
| Creazione/aggiornamento del sito; convalida dei campi dello spazio di lavoro | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
DELETE /v2/admin/sites/:siteId quando il sito ha dipendenze | 409 | { "error": "<message>", "code": "SITE_NOT_EMPTY" } |
GET /v2/admin/sites/geocode ricerca normalizzata non valida | 400 | { "error": "<message>", "code": "INVALID_GEOCODE_QUERY" } |
| Come sopra, coda limitata del fornitore piena | 429 | { "error": "<message>", "code": "GEOCODING_BUSY" }; include Retry-After se fornito dal geocodificatore |
| Come sopra, timeout/errore del fornitore o errore imprevisto del geocodificatore | 502 | { "error": "<message>", "code": "GEOCODING_UNAVAILABLE" }; un errore imprevisto usa Address search is temporarily unavailable |
PUT /v2/admin/sites/:siteId/power-management configurazione della topologia/del dominio non valida | 422 | { "error": "<message>", "code": "INVALID_POWER_MANAGEMENT_CONFIGURATION" } |
| Come sopra, rifiuto/timeout OCPP, modifica concorrente o conflitto di riconciliazione | 409 | { "error": "<message>", "code": "POWER_MANAGEMENT_CONFLICT" } |
Errori dei caricatori
mapChargerErrors() viene usato per creazione/aggiornamento dei caricatori, credenziali, impostazioni dei connettori, pubblicazione nell'elenco pubblico, risoluzione dei dati del codice QR, modifica/ricaricamento della configurazione, avvio del firmware, tutti e quattro i comandi di base e richiesta della pianificazione composita.
| Endpoint | Stato | Corpo esatto |
|---|---|---|
| Qualsiasi operazione precedente con errore di validazione delle regole di dominio | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Qualsiasi operazione precedente con conflitto di stato, unicità, offline/OCPP, fatturazione, modalità senza tag, connettore o disponibilità alla ricarica | 409 | { "error": "<message>", "code": "CHARGER_CONFLICT" } |
GET /chargers/:chargerId/sessions, intervallo di tempo predefinito/esplicito non valido | 422 | { "validationErrors": { "from": ["from must be before or equal to to"] } } o { "validationErrors": { "from": ["Session range cannot exceed 90 days"] } } |
Le semplici operazioni di lettura restituiscono solo le risposte comuni 401/403/404/429/500/503 e 422 per la convalida della query o del percorso. L'eliminazione di un caricatore può restituire la risposta comune 500 PlainError se non riesce senza una risposta di errore più specifica.
Errori dei report
| Endpoint | Stato | Corpo esatto |
|---|---|---|
Intervallo di dati/esportazione in cui from >= to | 422 | { "validationErrors": { "range": ["from must be earlier than to"] } } |
| Intervallo di dati/esportazione superiore a 90 giorni | 422 | { "validationErrors": { "range": ["Report ranges cannot exceed 90 days"] } } |
| Cursore opaco non valido per dati/misurazioni | 422 | { "validationErrors": { "cursor": ["<message>"] } } |
GET /reports/export, il risultato supera 2.000 righe | 422 | { "error": "<message>", "code": "REPORT_EXPORT_ROW_LIMIT", "limit": 2000 } |
POST /reports/send, nessuna pianificazione salvata | 409 | { "error": "A workspace report schedule must be saved before sending", "code": "REPORT_SCHEDULE_REQUIRED" } |
| Come sopra, il servizio email rifiuta l'invio o non riesce a eseguirlo | 502 | { "error": "Report delivery failed", "code": "REPORT_DELIVERY_FAILED" } |
| Risorsa di proprietà relativa a pianificazione/misurazioni assente | 404 | corpo comune RESOURCE_NOT_FOUND |
L'esportazione riuscita è binaria; tutti gli errori di esportazione rimangono JSON.
Errori delle tariffe
| Endpoint | Stato | Corpo esatto |
|---|---|---|
| Validazione di dominio per creazione/aggiornamento/componenti/prezzo di mercato/assegnazione | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Conflitto di stato, dipendenze o unicità nell'eliminazione o nell'assegnazione della tariffa | 409 | { "error": "<message>", "code": "TARIFF_CONFLICT" } |
| Tariffa, zona di mercato, caricatore, connettore, assegnazione della tariffa o altra risorsa annidata non appartenente al contesto di proprietà | 404 | corpo comune RESOURCE_NOT_FOUND |
Errori dei profili di ricarica
| Endpoint | Stato | Corpo esatto |
|---|---|---|
| Validazione di dominio per creazione/aggiornamento/programmazione/assegnazione | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Il profilo è richiamato da un utilizzo protetto | 409 | { "error": "<message>", "code": "CHARGING_PROFILE_IN_USE" } |
| Conflitto di sincronizzazione OCPP, assegnazione, concorrenza o altro conflitto del profilo | 409 | { "error": "<message>", "code": "CHARGING_PROFILE_CONFLICT" } |
| Profilo, caricatore, connettore, assegnazione o altra risorsa annidata non appartenente al contesto di proprietà | 404 | corpo comune RESOURCE_NOT_FOUND |
Errori del dominio utenti
Gli errori di convalida degli utenti che identificano un campo usano ValidationError insieme a code; gli altri errori degli utenti usano CodedError. Tutti i casi di risorse mancanti usano la risposta comune RESOURCE_NOT_FOUND, che non consente l'enumerazione delle risorse.
| Stato | Codice/i | 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" }; include 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 può anche restituire la risposta comune 403 INSUFFICIENT_SCOPE dopo l'analisi del corpo se manca users:access, oppure se è stato fornito un RFID e manca users:rfid. Gli endpoint degli utenti locali elencano tutti gli ambiti richiesti in Riferimento degli endpoint.
I codici di errore degli utenti si applicano come segue:
| Famiglia di endpoint | Codici del dominio utenti diversi da 404, oltre alle risposte comuni |
|---|---|
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) |
| Lettura dei dettagli degli utenti, dei veicoli e di RFID/accessi/limiti | nessun codice di dominio diverso da 404 |
| Creazione RFID | CUSTOMER_CONTRACT_MISSING, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_RFID (422) |
| Aggiornamento/eliminazione RFID | TAGLESS_USER_PROTECTED (409) |
| Sostituzione degli accessi | TAGLESS_USER_PROTECTED (409); NO_CHARGERS_AVAILABLE (422) |
| Revoca dell’accesso | TAGLESS_USER_PROTECTED (409) |
| Creazione/aggiornamento del limite | TAGLESS_USER_PROTECTED, LIMIT_ALREADY_EXISTS (409); INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE (422) |
| Eliminazione del limite | TAGLESS_USER_PROTECTED (409) |
| Creazione dell'invito nello spazio di lavoro | CUSTOMER_CONTRACT_MISSING, INVITATION_EMAIL_IN_USE, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL/INVALID_RFID (422); INVITATION_RESEND_THROTTLED (429) quando si applica l'intervallo minimo tra le consegne |
| Nuovo invio dell'invito nello spazio di lavoro | INVALID_EMAIL (422), INVITATION_RESEND_THROTTLED (429) |
| Annullamento dell'invito nello spazio di lavoro | INVALID_EMAIL (422) |
| Creazione di un utente locale del caricatore per un cliente esistente | LOCAL_USER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409) |
| Invito di un utente locale del caricatore | LOCAL_USER_ALREADY_EXISTS, INVITATION_EMAIL_IN_USE, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL (422); INVITATION_RESEND_THROTTLED (429) quando si applica l'intervallo minimo tra le consegne |
| Annullamento dell'invito di un utente locale | INVALID_EMAIL (422) |
| Aggiornamento/eliminazione di un utente locale | TAGLESS_USER_PROTECTED (409) |
Tutti gli esiti relativi a proprietà e risorse mancanti in queste famiglie, inclusa un’e-mail non registrata su POST /users, usano il corpo comune 404 RESOURCE_NOT_FOUND.
Risposte senza corpo e risposte riprodotte
Una risposta 204 riuscita non ha corpo. Questo vale per ogni eliminazione documentata che indica 204 empty. Una ripetizione idempotente completata imposta Idempotency-Replayed: true e usa lo stato e il corpo salvati; per 204, la risposta HTTP rimane senza corpo. L’API non restituisce mai un oggetto JSON di successo per un’operazione 204 documentata.