Договор за отговори и грешки на Admin API
Този файл допълва договора за отговори за всяка крайна точка в Справочник за крайни точки. Прочетете реда на крайната точка за успешното тяло и таблиците по-долу за всички общи или специфични неуспешни тела. По подразбиране грешките използват няколко съвместими структури; клиентите могат да изберат една универсална обвивка.
Незадължителна структурирана обвивка за грешки
Изпратете тази заглавка на заявката към която и да е крайна точка:
X-Error-Format: envelope
Стойността се сравнява след премахване на крайните интервали, без значение на регистъра. При точно тази стойност всеки JSON отговор със състояние 400 или по-високо се преобразува в:
ErrorEnvelope = {
error: {
code: string,
message: string,
details: Record<string, unknown>,
requestId: string
}
}
Примерно преобразуване на стандартно тяло за валидация:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Invalid request",
"details": {
"fields": {
"name": ["String must contain at least 1 character(s)"]
}
},
"requestId": "integration-42"
}
}
Правилата за преобразуване са точни:
validationErrorsставаdetails.fields, аcodeставаVALIDATION_FAILED, дори когато стандартното тяло има и домейн код.- При липса на полета за валидация се запазва
codeпо подразбиране на най-горно ниво. - Другите свойства на най-горно ниво, освен
error,message,validationErrorsиcode, се преместват вdetails; напримерlimitпри експорт на отчет ставаdetails.limit. - Текстово
errorна най-горно ниво ставаmessage. Ако липсва, се използва резервната стойност за състоянието. - Резервните кодове са
AUTH_REQUIRED(401),PERMISSION_DENIED(403),RESOURCE_NOT_FOUND(404),CONFLICT(409),VALIDATION_FAILED(422и други некласифицирани4xx),RATE_LIMITED(429),EXTERNAL_PROVIDER_FAILED(502) иINTERNAL_ERROR(други5xx, включително503). requestIdе точната заглавкаX-Request-Idна отговора. Подаден от клиента ID на заявка се използва само ако след премахване на крайните интервали съответства на[A-Za-z0-9._:-]{1,128}; иначе сървърът генерира UUID.
Преобразуването не променя състоянието или заглавките, несвързани с тялото. То важи и за идемпотентни повторения според заглавката X-Error-Format на повторената заявка. Двоичните успешни отговори остават двоични; JSON грешките им се обвиват. Останалите таблици показват стандартните тела; правилата по-горе дават другото възможно тяло за всеки ред.
Нотация на отговорите
ValidationError = {
validationErrors: Record<string, string[]>,
code?: string
}
CodedError = {
error: string,
code: string,
// a route may add fields explicitly listed below
}
PlainError = { error: string }
error и текстът на съобщението за валидация са описателни, а не стабилен програмен разграничител. Разграничавайте по code, когато присъства. Валидацията на заявката връща 422 ValidationError; валидацията на цял обект може да даде { "validationErrors": {} }, когато не е посочено отделно поле. Невалиден JSON и неочаквани грешки връщат глобалното 500 PlainError, показано по-долу.
Всички JSON примери показват точната структура на тялото. Текстът <message> е върнатото съобщение за валидация или операция и представлява JSON низ, а не буквална стойност в ъглови скоби.
Ред на обработка на заявки
Заявките се обработват в този ред:
- конфигурация и удостоверяване с токен на работно пространство;
- политика на хоста и лимити на заявки за токен/работно пространство;
- филтриране по текущи права;
- за всяка промяна — валидация/заявяване на идемпотентност;
- проверки на обхвата на крайната точка, валидация на заявката и заявената операция.
Следователно промяна с валиден токен, но недостатъчен обхват, все пак трябва да изпрати Idempotency-Key. Завършен отговор за промяна 403, 404, 409 или 422 може да бъде повторен със същия ключ/заявка.
Отговори за удостоверяване, политики и ограничаване на заявки
Тези отговори могат да възникнат на всяка регистрирана крайна точка /v2/admin преди специфичната ѝ обработка.
| Състояние | Кога | Точно тяло | Приложими заглавки |
|---|---|---|---|
401 | Липсващ, дублиран, съединен със запетая, не-Bearer, неправилно оформен, непознат, изтекъл, отнет или иначе невалиден токен на работното пространство | { "error": "Unauthorized", "code": "INVALID_WORKSPACE_TOKEN" } | WWW-Authenticate: Bearer, Cache-Control: no-store |
404 | Токенът е валиден, но хостът на работното му пространство няма adminApiEnabled | { "error": "Not Found" } | Cache-Control: no-store |
429 | Лимитът на заявките за токен или работно пространство е изчерпан | { "error": "Too many attempts. Please try again later." } | Retry-After: <seconds> |
503 | Удостоверяването с токен на работно пространство временно не е достъпно | { "error": "Admin API workspace-token configuration is unavailable", "code": "WORKSPACE_API_CONFIG_UNAVAILABLE" } | — |
503 | Проверката на политиката на хоста или оторизацията на текущите права е неуспешна | { "error": "Workspace authorization is temporarily unavailable", "code": "WORKSPACE_AUTHORIZATION_UNAVAILABLE" } | — |
API достъпът е включен във всеки план. Изключването на adminApiEnabled за хоста на работното пространство връща 404; загубата на допълнително право за функция премахва само засегнатите обхвати. Полученият отказ за обхват използва отговора по-долу, а не процес за обновяване на токен.
Обхват, идемпотентност, парсване, собственост и неочаквани грешки
| Прилага се за | Състояние | Точно тяло | Заглавки/бележки |
|---|---|---|---|
| Всеки маршрут след удостоверяване | 403 | { "error": "Insufficient workspace-token scope", "code": "INSUFFICIENT_SCOPE" } | Връща се, когато липсва който и да е задължителен обхват. |
| Всяка промяна | 400 | { "error": "Idempotency-Key is required for this operation", "code": "IDEMPOTENCY_KEY_REQUIRED" } | Не е подаден ключ. |
| Всяка промяна | 400 | { "error": "Exactly one Idempotency-Key is required", "code": "INVALID_IDEMPOTENCY_KEY" } | Дублирана или съединена със запетая заглавка. |
| Всяка промяна | 400 | { "error": "Idempotency-Key must contain 1 to 255 visible characters", "code": "INVALID_IDEMPOTENCY_KEY" } | Празно, твърде дълго или съдържа контролен знак. |
| Всяка промяна | 409 | { "error": "Idempotency-Key was already used with a different request", "code": "IDEMPOTENCY_CONFLICT" } | Същите токен/метод/път/ключ, различни URL или тяло. |
| Всяка промяна | 409 | { "error": "Request is already processing", "code": "IDEMPOTENT_REQUEST_PROCESSING" } | Retry-After: 5. |
| Всяка промяна | 409 | { "error": "Previous request outcome is unknown; verify its effects before attempting the operation again", "code": "IDEMPOTENCY_OUTCOME_UNKNOWN" } | Предишният наем за обработка е изтекъл, връзката е затворена или заявката е приключила с 5xx. |
| Всяка промяна | 503 | { "error": "Idempotency storage unavailable", "code": "IDEMPOTENCY_UNAVAILABLE" } | API не може да провери или запази записа за идемпотентност. |
| Всяка крайна точка с невалидна схема на заявката/тялото/пътя | 422 | { "validationErrors": { "<field>": ["<message>"] } } | Може да има няколко полета/съобщения. Клиентите не могат да подават cpoId; работното пространство винаги идва от токена. |
| Всеки липсващ вложен ресурс или идентификатор от друго работно пространство | 404 | { "error": "Workspace resource not found", "code": "RESOURCE_NOT_FOUND" } | Използва се последователно, освен ако таблица по-долу не посочва друго. |
| Всяка крайна точка с неочаквана грешка | 500 | { "error": "Something went wrong" } | При промени повторен опит със същия ключ по-късно дава 409 IDEMPOTENCY_OUTCOME_UNKNOWN. |
ID на ресурсите в пътя трябва да са положителни числа. Неположително или нечислово :siteId, :chargerId, :portId, :tariffId, :profileId, :assignmentId, :userId, :rfidId, :accessId, :limitId или :localUserId връща 422 ValidationError, а не 400.
Грешки на обекти и управление на мощността
| Крайни точки | Състояние | Точно тяло |
|---|---|---|
| Създаване/актуализация на обект; валидация на полета на работното пространство | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
DELETE /v2/admin/sites/:siteId, когато обектът има зависимости | 409 | { "error": "<message>", "code": "SITE_NOT_EMPTY" } |
GET /v2/admin/sites/geocode невалидно нормализирано търсене | 400 | { "error": "<message>", "code": "INVALID_GEOCODE_QUERY" } |
| Същото, ограничената опашка на доставчика е пълна | 429 | { "error": "<message>", "code": "GEOCODING_BUSY" }; включва Retry-After, когато е предоставено от геокодера |
| Същото, изтекло време/грешка на доставчика или неочаквана грешка на геокодера | 502 | { "error": "<message>", "code": "GEOCODING_UNAVAILABLE" }; неочаквана грешка използва Address search is temporarily unavailable |
PUT /v2/admin/sites/:siteId/power-management невалидна топология/домейн конфигурация | 422 | { "error": "<message>", "code": "INVALID_POWER_MANAGEMENT_CONFIGURATION" } |
| Същото, отказ/изтекло време на OCPP, паралелна промяна или конфликт при съгласуване | 409 | { "error": "<message>", "code": "POWER_MANAGEMENT_CONFLICT" } |
Грешки на станции
mapChargerErrors() се използва за създаване/актуализация на станция, данни за достъп, настройки на конектор, публично показване, разрешаване на QR съдържание, промяна/презареждане на конфигурация, стартиране на фърмуер, всичките четири основни команди и заявка за съставен график.
| Крайни точки | Състояние | Точно тяло |
|---|---|---|
| Всяка горна операция с грешка при валидация на домейна | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Всяка горна операция с конфликт на състояние, уникалност, офлайн/OCPP, плащане, Tagless, конектор или готовност | 409 | { "error": "<message>", "code": "CHARGER_CONFLICT" } |
GET /chargers/:chargerId/sessions, невалиден стандартен/изричен времеви период | 422 | { "validationErrors": { "from": ["from must be before or equal to to"] } } или { "validationErrors": { "from": ["Session range cannot exceed 90 days"] } } |
Обикновените операции за четене връщат само общите отговори 401/403/404/429/500/503 и валидация 422 на заявката/пътя. Изтриването на станция може да върне общото 500 PlainError, ако е неуспешно без по-конкретен отговор за грешка.
Грешки на отчети
| Крайни точки | Състояние | Точно тяло |
|---|---|---|
Период на данни/експорт, при който from >= to | 422 | { "validationErrors": { "range": ["from must be earlier than to"] } } |
| Период на данни/експорт над 90 дни | 422 | { "validationErrors": { "range": ["Report ranges cannot exceed 90 days"] } } |
| Невалиден непрозрачен курсор за данни/измервания | 422 | { "validationErrors": { "cursor": ["<message>"] } } |
GET /reports/export, резултатът надхвърля 2000 реда | 422 | { "error": "<message>", "code": "REPORT_EXPORT_ROW_LIMIT", "limit": 2000 } |
POST /reports/send, няма запазен график | 409 | { "error": "A workspace report schedule must be saved before sending", "code": "REPORT_SCHEDULE_REQUIRED" } |
| Същото, пощенската услуга отказва/е неуспешна | 502 | { "error": "Report delivery failed", "code": "REPORT_DELIVERY_FAILED" } |
| Липсва собствен ресурс за график/измервания | 404 | общо тяло RESOURCE_NOT_FOUND |
Успешният експорт е двоичен; всички грешки при експорт остават JSON.
Грешки на тарифи
| Крайни точки | Състояние | Точно тяло |
|---|---|---|
| Домейн валидация при създаване/актуализация/компоненти/пазарни цени/присвояване | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Конфликт на състояние/зависимост/уникалност при изтриване или присвояване на тарифа | 409 | { "error": "<message>", "code": "TARIFF_CONFLICT" } |
| Тарифа, ценова зона, станция, конектор, присвояване на тарифа или друг вложен ресурс не принадлежи на собственика | 404 | общо тяло RESOURCE_NOT_FOUND |
Грешки на профили за зареждане
| Крайни точки | Състояние | Точно тяло |
|---|---|---|
| Домейн валидация при създаване/актуализация/график/присвояване | 422 | { "validationErrors": { "<field>": ["<message>"] } } |
| Профилът се използва от защитена употреба | 409 | { "error": "<message>", "code": "CHARGING_PROFILE_IN_USE" } |
| Конфликт на OCPP синхронизация, присвояване, паралелна промяна или друг конфликт на профил | 409 | { "error": "<message>", "code": "CHARGING_PROFILE_CONFLICT" } |
| Профил, станция, конектор, присвояване или друг вложен ресурс не принадлежи на собственика | 404 | общо тяло RESOURCE_NOT_FOUND |
Грешки в потребителския домейн
Грешките при валидация на потребител, посочващи поле, използват ValidationError и code; останалите потребителски грешки използват CodedError. Всички случаи на липсващ ресурс използват общия отговор RESOURCE_NOT_FOUND, който не разкрива съществуването на ресурси.
| Състояние | Код(ове) | Тяло |
|---|---|---|
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" }; включва 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 може да върне и общото 403 INSUFFICIENT_SCOPE след парсване на тялото, ако липсва users:access, или ако е подаден RFID и липсва users:rfid. Крайните точки за локални потребители изброяват всеки задължителен обхват в Справочник за крайни точки.
Кодовете за потребителски грешки се прилагат така:
| Група крайни точки | Домейн кодове за потребители, различни от 404, в допълнение към общите отговори |
|---|---|
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) |
| Четене на детайли на потребител, автомобили, RFID/достъп/лимити | няма домейн код, различен от 404 |
| Създаване на RFID | CUSTOMER_CONTRACT_MISSING, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_RFID (422) |
| Актуализация/изтриване на RFID | TAGLESS_USER_PROTECTED (409) |
| Замяна на достъп | TAGLESS_USER_PROTECTED (409); NO_CHARGERS_AVAILABLE (422) |
| Отнемане на достъп | TAGLESS_USER_PROTECTED (409) |
| Създаване/актуализация на лимит | TAGLESS_USER_PROTECTED, LIMIT_ALREADY_EXISTS (409); INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE (422) |
| Изтриване на лимит | TAGLESS_USER_PROTECTED (409) |
| Създаване на покана за работно пространство | CUSTOMER_CONTRACT_MISSING, INVITATION_EMAIL_IN_USE, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL/INVALID_RFID (422); INVITATION_RESEND_THROTTLED (429), когато важи изчакване за доставка |
| Повторно изпращане на покана за работно пространство | INVALID_EMAIL (422), INVITATION_RESEND_THROTTLED (429) |
| Отмяна на покана за работно пространство | INVALID_EMAIL (422) |
| Създаване на локален потребител на станция за съществуващ клиент | LOCAL_USER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409) |
| Покана за локален потребител на станция | LOCAL_USER_ALREADY_EXISTS, INVITATION_EMAIL_IN_USE, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL (422); INVITATION_RESEND_THROTTLED (429), когато важи изчакване за доставка |
| Отмяна на покана за локален потребител | INVALID_EMAIL (422) |
| Актуализация/изтриване на локален потребител | TAGLESS_USER_PROTECTED (409) |
Всички резултати за собственост и липсващи ресурси в тези групи, включително нерегистриран имейл при POST /users, използват общото тяло 404 RESOURCE_NOT_FOUND.
Отговори без тяло и при повторение
Успешният отговор 204 няма тяло. Това важи за всяко документирано изтриване с 204 empty. Завършено идемпотентно повторение задава Idempotency-Replayed: true и използва запазените състояние/тяло; за 204 HTTP отговорът остава без тяло. API никога не връща успешен JSON обект за документирана операция 204.