Odpowiedzi i błędy

Kontrakt odpowiedzi i błędów API administracyjnego

Ten plik uzupełnia kontrakt odpowiedzi dla każdego punktu końcowego w Dokumentacji punktów końcowych. Treść pomyślnej odpowiedzi znajdziesz w wierszu punktu końcowego, a wszystkie wspólne i specyficzne treści niepowodzeń w tabelach poniżej. Domyślnie błędy używają kilku struktur zgodności; wywołujący mogą wybrać jedno uniwersalne opakowanie.

Opcjonalne ustrukturyzowane opakowanie błędu

Wyślij ten nagłówek żądania do dowolnego punktu końcowego:

X-Error-Format: envelope

Porównanie wartości usuwa skrajne spacje i nie rozróżnia wielkości liter. Przy tej dokładnej wartości każda odpowiedź JSON ze statusem 400 lub wyższym jest konwertowana do:

ErrorEnvelope = {
  error: {
    code: string,
    message: string,
    details: Record<string, unknown>,
    requestId: string
  }
}

Przykład konwersji domyślnej treści walidacji:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Invalid request",
    "details": {
      "fields": {
        "name": ["String must contain at least 1 character(s)"]
      }
    },
    "requestId": "integration-42"
  }
}

Reguły konwersji są dokładne:

  • validationErrors staje się details.fields, a code staje się VALIDATION_FAILED, nawet jeśli domyślna treść zawierała również kod domenowy.
  • Domyślne pole code najwyższego poziomu jest zachowywane, gdy nie ma pól walidacji.
  • Pozostałe właściwości najwyższego poziomu, poza error, message, validationErrors i code, są przenoszone do details; na przykład limit eksportu raportu staje się details.limit.
  • Pole tekstowe error najwyższego poziomu staje się message. Jeśli go nie ma, używany jest domyślny komunikat dla statusu.
  • Kody zastępcze to AUTH_REQUIRED (401), PERMISSION_DENIED (403), RESOURCE_NOT_FOUND (404), CONFLICT (409), VALIDATION_FAILED (422 i inne niesklasyfikowane 4xx), RATE_LIMITED (429), EXTERNAL_PROVIDER_FAILED (502) i INTERNAL_ERROR (inne 5xx, w tym 503).
  • requestId to dokładny nagłówek odpowiedzi X-Request-Id. Identyfikator żądania podany przez wywołującego jest używany tylko wtedy, gdy po usunięciu skrajnych spacji pasuje do [A-Za-z0-9._:-]{1,128}; w przeciwnym razie serwer generuje UUID.

Ta transformacja nie zmienia statusu ani nagłówków niezwiązanych z treścią. Dotyczy też powtórzeń idempotentnych według nagłówka X-Error-Format żądania powtórzenia. Pomyślne odpowiedzi binarne pozostają binarne; ich błędy JSON są opakowywane. Pozostałe tabele pokazują domyślne treści; zastosowanie powyższych reguł daje drugą możliwą treść odpowiedzi dla każdego wiersza.

Oznaczenia odpowiedzi

ValidationError = {
  validationErrors: Record<string, string[]>,
  code?: string
}

CodedError = {
  error: string,
  code: string,
  // a route may add fields explicitly listed below
}

PlainError = { error: string }

error i tekst komunikatu walidacji mają charakter opisowy, a nie stanowią stabilnego kryterium programowego. Opieraj decyzje na code, jeśli występuje. Walidacja żądania zwraca 422 ValidationError; walidacja całego obiektu może dać { "validationErrors": {} }, gdy nie wskazano pojedynczego pola. Nieprawidłowy JSON i nieoczekiwane awarie zwracają globalne 500 PlainError pokazane poniżej.

Wszystkie przykłady JSON pokazują dokładną strukturę treści. Tekst przedstawiony jako <message> to zwrócony komunikat walidacji lub operacji i jest ciągiem JSON, a nie dosłowną wartością w nawiasach ostrych.

Kolejność przetwarzania żądań

Żądania są przetwarzane w następującej kolejności:

  1. konfiguracja i uwierzytelnianie tokena obszaru roboczego;
  2. polityka dostawcy i limity częstotliwości tokena/obszaru roboczego;
  3. filtrowanie bieżących uprawnień do funkcji;
  4. dla każdej operacji zmieniającej dane — walidacja i rezerwacja klucza idempotencji;
  5. sprawdzenie zakresów uprawnień punktu końcowego, walidacja żądania i żądana operacja.

W konsekwencji operacja zmieniająca dane z prawidłowym tokenem, ale niewystarczającymi zakresami uprawnień, nadal musi przesłać Idempotency-Key. Zakończoną odpowiedź operacji 403, 404, 409 lub 422 można odtworzyć dla tego samego klucza i żądania.

Odpowiedzi uwierzytelniania, polityk i ograniczania częstotliwości żądań

Te odpowiedzi mogą wystąpić w każdym zarejestrowanym punkcie końcowym /v2/admin przed przetwarzaniem właściwym dla punktu końcowego.

StatusKiedyDokładna treśćIstotne nagłówki
401Brakujący, powielony, połączony przecinkami token obszaru roboczego, token z innym schematem niż Bearer, niepoprawnie sformatowany, nieznany, wygasły, cofnięty lub w inny sposób nieprawidłowy{ "error": "Unauthorized", "code": "INVALID_WORKSPACE_TOKEN" }WWW-Authenticate: Bearer, Cache-Control: no-store
404Token jest prawidłowy, ale dostawca jego obszaru roboczego nie ma adminApiEnabled{ "error": "Not Found" }Cache-Control: no-store
429Wyczerpano pulę żądań tokena lub obszaru roboczego{ "error": "Too many attempts. Please try again later." }Retry-After: <seconds>
503Uwierzytelnianie tokenem obszaru roboczego jest tymczasowo niedostępne{ "error": "Admin API workspace-token configuration is unavailable", "code": "WORKSPACE_API_CONFIG_UNAVAILABLE" }—
503Niepowodzenie pobierania polityki dostawcy lub autoryzacji bieżących uprawnień do funkcji{ "error": "Workspace authorization is temporarily unavailable", "code": "WORKSPACE_AUTHORIZATION_UNAVAILABLE" }—

Dostęp do API jest zawarty w każdym planie. Wyłączenie ustawienia adminApiEnabled u dostawcy obszaru roboczego powoduje zwrócenie 404; utrata dodatkowego uprawnienia do funkcji usuwa tylko powiązane zakresy. Wynikowa odmowa dostępu do zakresu używa odpowiedzi poniżej, a nie procedury odświeżania tokena.

Błędy zakresu uprawnień, idempotencji, parsowania, własności i nieoczekiwane awarie

DotyczyStatusDokładna treśćNagłówki/uwagi
Każda ścieżka po uwierzytelnieniu403{ "error": "Insufficient workspace-token scope", "code": "INSUFFICIENT_SCOPE" }Zwracane, gdy brakuje któregokolwiek wymaganego zakresu uprawnień.
Każda operacja zmieniająca dane400{ "error": "Idempotency-Key is required for this operation", "code": "IDEMPOTENCY_KEY_REQUIRED" }Nie podano klucza.
Każda operacja zmieniająca dane400{ "error": "Exactly one Idempotency-Key is required", "code": "INVALID_IDEMPOTENCY_KEY" }Powielony nagłówek lub wartości połączone przecinkiem.
Każda operacja zmieniająca dane400{ "error": "Idempotency-Key must contain 1 to 255 visible characters", "code": "INVALID_IDEMPOTENCY_KEY" }Puste, zbyt długie lub zawierające znak sterujący.
Każda operacja zmieniająca dane409{ "error": "Idempotency-Key was already used with a different request", "code": "IDEMPOTENCY_CONFLICT" }Ten sam token/metoda/ścieżka/klucz, ale inny URL lub treść.
Każda operacja zmieniająca dane409{ "error": "Request is already processing", "code": "IDEMPOTENT_REQUEST_PROCESSING" }Retry-After: 5.
Każda operacja zmieniająca dane409{ "error": "Previous request outcome is unknown; verify its effects before attempting the operation again", "code": "IDEMPOTENCY_OUTCOME_UNKNOWN" }Wygasła poprzednia rezerwacja przetwarzania, połączenie zostało zamknięte lub żądanie zakończyło się kodem 5xx.
Każda operacja zmieniająca dane503{ "error": "Idempotency storage unavailable", "code": "IDEMPOTENCY_UNAVAILABLE" }API nie może sprawdzić lub zapisać rekordu idempotencji.
Dowolny punkt końcowy z nieprawidłowym schematem zapytania, treści lub ścieżki422{ "validationErrors": { "<field>": ["<message>"] } }Może wystąpić wiele pól lub komunikatów. Wywołujący nie mogą podawać cpoId; obszar roboczy zawsze pochodzi z tokena.
Dowolny brak zagnieżdżonego zasobu obszaru roboczego lub identyfikator z innego obszaru roboczego404{ "error": "Workspace resource not found", "code": "RESOURCE_NOT_FOUND" }Stosowane konsekwentnie, chyba że tabela poniżej stanowi inaczej.
Dowolny punkt końcowy z nieoczekiwanym błędem500{ "error": "Something went wrong" }W przypadku operacji zmieniających dane późniejsze ponowienie tego samego klucza daje 409 IDEMPOTENCY_OUTCOME_UNKNOWN.

Identyfikatory zasobów w ścieżce muszą być dodatnimi liczbami. Niedodatnie lub nieliczbowe :siteId, :chargerId, :portId, :tariffId, :profileId, :assignmentId, :userId, :rfidId, :accessId, :limitId lub :localUserId zwraca 422 ValidationError, a nie 400.

Błędy lokalizacji i zarządzania mocą

Punkty końcoweStatusDokładna treść
Tworzenie/aktualizacja lokalizacji; walidacja pól obszaru roboczego422{ "validationErrors": { "<field>": ["<message>"] } }
DELETE /v2/admin/sites/:siteId, gdy lokalizacja ma zależności409{ "error": "<message>", "code": "SITE_NOT_EMPTY" }
GET /v2/admin/sites/geocode nieprawidłowe znormalizowane wyszukiwanie400{ "error": "<message>", "code": "INVALID_GEOCODE_QUERY" }
To samo, zapełniona ograniczona kolejka dostawcy429{ "error": "<message>", "code": "GEOCODING_BUSY" }; zawiera Retry-After, gdy geokoder je dostarczy
To samo, przekroczenie czasu/awaria dostawcy lub nieoczekiwany błąd geokodera502{ "error": "<message>", "code": "GEOCODING_UNAVAILABLE" }; nieoczekiwany błąd używa Address search is temporarily unavailable
PUT /v2/admin/sites/:siteId/power-management nieprawidłowa konfiguracja topologii/domeny422{ "error": "<message>", "code": "INVALID_POWER_MANAGEMENT_CONFIGURATION" }
To samo, odmowa OCPP/przekroczenie czasu, wyścig współbieżnych operacji lub konflikt uzgadniania409{ "error": "<message>", "code": "POWER_MANAGEMENT_CONFLICT" }

Błędy ładowarek

mapChargerErrors() jest używane przy tworzeniu/aktualizacji ładowarki, danych uwierzytelniających, ustawieniach złącza, publicznym udostępnianiu, rozwiązywaniu danych QR, zmianie/ponownym wczytywaniu konfiguracji, uruchamianiu aktualizacji oprogramowania układowego, wszystkich czterech podstawowych poleceniach i żądaniu harmonogramu zbiorczego.

Punkty końcoweStatusDokładna treść
Dowolna powyższa operacja z błędem walidacji reguł domenowych422{ "validationErrors": { "<field>": ["<message>"] } }
Dowolna powyższa operacja z konfliktem stanu, unikalności, trybu offline/OCPP, rozliczeń, trybu bez identyfikatora, złącza lub gotowości409{ "error": "<message>", "code": "CHARGER_CONFLICT" }
GET /chargers/:chargerId/sessions, nieprawidłowy domyślny lub jawnie podany zakres czasu422{ "validationErrors": { "from": ["from must be before or equal to to"] } } lub { "validationErrors": { "from": ["Session range cannot exceed 90 days"] } }

Zwykłe operacje odczytu zwracają tylko wspólne odpowiedzi 401/403/404/429/500/503 oraz 422 dla walidacji zapytania lub ścieżki. Usuwanie ładowarki może zwrócić wspólne 500 PlainError, jeśli usunięcie nie powiedzie się bez bardziej szczegółowej odpowiedzi błędu.

Błędy raportów

Punkty końcoweStatusDokładna treść
Zakres danych/eksportu, w którym from >= to422{ "validationErrors": { "range": ["from must be earlier than to"] } }
Zakres danych/eksportu przekracza 90 dni422{ "validationErrors": { "range": ["Report ranges cannot exceed 90 days"] } }
Nieprawidłowy nieprzezroczysty kursor danych/pomiarów422{ "validationErrors": { "cursor": ["<message>"] } }
GET /reports/export, wynik przekracza 2000 wierszy422{ "error": "<message>", "code": "REPORT_EXPORT_ROW_LIMIT", "limit": 2000 }
POST /reports/send, brak zapisanego harmonogramu409{ "error": "A workspace report schedule must be saved before sending", "code": "REPORT_SCHEDULE_REQUIRED" }
To samo, system pocztowy odrzuca lub ulega awarii502{ "error": "Report delivery failed", "code": "REPORT_DELIVERY_FAILED" }
Brak należącego do obszaru zasobu harmonogramu/pomiarów404wspólna treść RESOURCE_NOT_FOUND

Pomyślny eksport jest binarny; wszystkie błędy eksportu pozostają w JSON.

Błędy taryf

Punkty końcoweStatusDokładna treść
Walidacja reguł domenowych tworzenia/aktualizacji/składników/ceny rynkowej/przypisania422{ "validationErrors": { "<field>": ["<message>"] } }
Konflikt usuwania taryfy lub stanu/zależności/unikalności przypisania409{ "error": "<message>", "code": "TARIFF_CONFLICT" }
Brak należącej do obszaru taryfy, strefy rynkowej, ładowarki, złącza, przypisania taryfy lub innego zagnieżdżonego zasobu404wspólna treść RESOURCE_NOT_FOUND

Błędy profili ładowania

Punkty końcoweStatusDokładna treść
Walidacja reguł domenowych tworzenia/aktualizacji/harmonogramu/przypisania422{ "validationErrors": { "<field>": ["<message>"] } }
Profil jest używany w chronionym zastosowaniu409{ "error": "<message>", "code": "CHARGING_PROFILE_IN_USE" }
Konflikt synchronizacji OCPP, przypisania, współbieżności lub inny konflikt profilu409{ "error": "<message>", "code": "CHARGING_PROFILE_CONFLICT" }
Brak należącego do obszaru profilu, ładowarki, złącza, przypisania lub innego zagnieżdżonego zasobu404wspólna treść RESOURCE_NOT_FOUND

Błędy domeny użytkowników

Błędy walidacji użytkownika wskazujące pole używają ValidationError i code; inne błędy użytkownika używają CodedError. Wszystkie przypadki brakujących zasobów używają wspólnej odpowiedzi RESOURCE_NOT_FOUND, która nie ujawnia istnienia zasobu.

StatusKod(y)Treść
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" }; zawiera 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 może również zwrócić wspólne 403 INSUFFICIENT_SCOPE po sparsowaniu treści, jeśli brakuje users:access albo podano RFID i brakuje users:rfid. Punkty końcowe użytkowników lokalnych wymieniają każdy wymagany zakres w Dokumentacji punktów końcowych.

Kody błędów użytkownika obowiązują następująco:

Grupa punktów końcowychKody domeny użytkowników inne niż 404, dodatkowe wobec wspólnych odpowiedzi
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)
Szczegóły użytkownika, pojazdy i odczyty RFID/dostępu/limitówbrak kodu domenowego innego niż 404
Tworzenie RFIDCUSTOMER_CONTRACT_MISSING, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_RFID (422)
Aktualizacja/usuwanie RFIDTAGLESS_USER_PROTECTED (409)
Zastąpienie dostępuTAGLESS_USER_PROTECTED (409); NO_CHARGERS_AVAILABLE (422)
Cofnięcie dostępuTAGLESS_USER_PROTECTED (409)
Tworzenie/aktualizacja limituTAGLESS_USER_PROTECTED, LIMIT_ALREADY_EXISTS (409); INVALID_LIMIT_TYPE, INVALID_LIMIT_VALUE (422)
Usuwanie limituTAGLESS_USER_PROTECTED (409)
Tworzenie zaproszenia do obszaru roboczegoCUSTOMER_CONTRACT_MISSING, INVITATION_EMAIL_IN_USE, RFID_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL/INVALID_RFID (422); INVITATION_RESEND_THROTTLED (429), gdy obowiązuje odstęp między wysyłkami
Ponowne wysyłanie zaproszenia do obszaru roboczegoINVALID_EMAIL (422), INVITATION_RESEND_THROTTLED (429)
Anulowanie zaproszenia do obszaru roboczegoINVALID_EMAIL (422)
Tworzenie lokalnego użytkownika ładowarki dla istniejącego klientaLOCAL_USER_ALREADY_EXISTS, TAGLESS_USER_PROTECTED (409)
Zaproszenie lokalnego użytkownika ładowarkiLOCAL_USER_ALREADY_EXISTS, INVITATION_EMAIL_IN_USE, TAGLESS_USER_PROTECTED (409); INVALID_EMAIL (422); INVITATION_RESEND_THROTTLED (429), gdy obowiązuje odstęp między wysyłkami
Anulowanie zaproszenia użytkownika lokalnegoINVALID_EMAIL (422)
Aktualizacja/usuwanie użytkownika lokalnegoTAGLESS_USER_PROTECTED (409)

Wszystkie wyniki dotyczące własności i brakujących zasobów w tych grupach, w tym niezarejestrowany adres e-mail w POST /users, używają wspólnej treści 404 RESOURCE_NOT_FOUND.

Odpowiedzi bez treści i odpowiedzi na powtórzenia

Pomyślna odpowiedź 204 nie ma treści. Dotyczy to każdej udokumentowanej operacji usunięcia, przy której wymieniono 204 empty. Zakończone powtórzenie idempotentne ustawia Idempotency-Replayed: true i używa zapisanego statusu oraz treści; dla 204 odpowiedź HTTP nadal nie ma treści. API nigdy nie zwraca obiektu JSON potwierdzającego powodzenie dla udokumentowanej operacji 204.