Endpoints

Endpointanrop och svar i arbetsytans Admin API

Detta är anrops- och svarsreferensen för varje /v2/admin-endpoint. Autentisering, idempotens, anropsgränser, tokenskapande och behörighetsområdenas betydelse dokumenteras i Workspace Admin API. Återanvändbara fälttyper och exempel finns i Scheman och exempel. Läs varje endpointrad tillsammans med Kontrakt för svar och fel, som listar alla möjliga gemensamma och endpointspecifika svarskroppar vid fel.

Gemensamt kontrakt

Varje sökväg börjar med den driftsatta app-api-serverns ursprung. Arbetsytan härleds uteslutande från den autentiserade token; klienter får inte skicka cpoId. Alla dokumenterade resursvärden :...Id i sökvägen är positiva decimala heltal. Varje anrop kräver exakt en:

Authorization: Bearer <workspace-access-token>

Anrop som visas med JSON-kropp kräver Content-Type: application/json. Alla ändringsåtgärder kräver Idempotency-Key (POST, PUT, PATCH och DELETE), inklusive POST /v2/admin/reports/send; om inget annat anges är innehållstypen vid framgång application/json, JSON-datum är RFC 3339-strängar och tal är JSON-tal.

Varje anrop får innehålla X-Request-Id och X-Error-Format: envelope; se Kontrakt för svar och fel. Dessa headrar ändrar inte scheman för lyckade svar.

Notation som används nedan:

  • none betyder ingen anropskropp. En DELETE som dokumenterar en JSON-kropp kräver fortfarande den kroppen.
  • ? markerar en valfri egenskap eller frågeparameter.
  • T | null betyder att egenskapen finns och får vara null.
  • 204 empty betyder ingen svarskropp.
  • CursorPage<T> betyder { items: T[], nextCursor: number|string|null }, utom där raden uttryckligen nämner ett page- eller pagination-objekt.
  • Alla saknade underordnade resurser, även ID:n från andra arbetsytor, använder 404 { "error": "Workspace resource not found", "code": "RESOURCE_NOT_FOUND" } om inte en funktion dokumenterar en mer specifik konflikt.

Gemensamma anropsscheman

Indata för arbetsytor och platser

WorkspacePatch = {
  name?: string(1..100), email?: email|null, website?: string|null,
  addressLine1?: string|null, addressLine2?: string|null,
  postalCode?: string|null, city?: string|null, state?: string|null,
  countryId?: positive integer
} // at least one property

SiteInput = {
  name: string(1..255), description?: string|null = null,
  addressLine1?: string|null = null, addressLine2?: string|null = null,
  postalCode?: string|null = null, city?: string|null = null, state?: string|null = null,
  countryId: positive integer, timezoneId: positive integer,
  latitude?: number[-90,90]|null = null, longitude?: number[-180,180]|null = null
}

Indata för effektstyrning

PowerConfigurationInput = { pools: PowerPoolInput[0..200] }
PowerPoolInput = {
  id?: positive integer|null, name?: string(0..255),
  limit: integer[0,100000000], meterSources?: ExternalMeterInput[0..16],
  children?: (PowerPoolInput | ChargerPoolChild)[0..1000]
}
ChargerPoolChild = { chargepointId: positive integer, priority?: integer[-1000000,1000000] }
ExternalMeterInput = {
  id?: positive integer|null, sourceId?: positive integer|null,
  provider?: "perific", name?: string(0..255), externalId: string(1..80),
  measurementMode?: "available_headroom"|"external_non_ev_load_only"|"total_site_load_including_ev",
  valueMode?: "perific_relative"|"perific_direct"|"perific_meter",
  reserveA?: integer[0,100000], offlineSafeA?: integer[0,100000],
  ttlSeconds?: integer[30,86400], enabled?: boolean
}

Laddarindata

ChargerCreate = { name: string(1..40), identifier: string(1..40), password?: string(0..40) = "", siteId: positive integer }
ChargerPatch = {
  name?: string(1..40), siteId?: positive integer, invertedRfid?: boolean,
  smartMode?: integer[0,3], automationDisabled?: boolean
} // at least one
ConnectorPatch = {
  connectorFormatId: positive integer, connectorTypeId: positive integer,
  powerTypeId: positive integer, maxVoltage: integer[1,10000],
  maxAmperage: integer[1,10000], maxElectricPower: integer[1,100000000]
}

Rapportindata

ReportFilters = {
  from?: RFC3339, to?: RFC3339, siteId?: positive integer,
  chargerId?: positive integer, userId?: positive integer,
  anonymous?: true|false|1|0, active?: true|false|1|0
}
ReportScheduleInput = {
  enabled: boolean, recipientEmail: email(max 255; may be empty only when disabled), format: "csv"|"pdf",
  sendDay: integer[1,28], sendTime: UTC "HH:mm"
}

Rapportintervall måste uppfylla from < to och får inte överstiga 90 dagar. Vid utelämnande används de senaste 90 dagarna. userId och anonymous=true utesluter varandra. Schemalagda exporter körs i efterhand efter en missad UTC-minut och använder begränsade återförsök: 5/10 minuters väntetid, 30 minuters reservation för inaktuella behandlingsanspråk och tre försök.

Tariffindata

TariffInput = {
  name: string(1..64),
  exactly one of currencyId: positive integer, currencyCode: 3 letters, currency: 3 letters,
  biddingZoneId?: positive integer|null, tax?: finite number
}
TariffComponentInput = {
  typeId: positive integer, seasonId: positive integer, priority?: finite number,
  price: finite number, validFromMonth?: finite number, validToMonth?: finite number,
  validFromWeekDay?: finite number, validToWeekDay?: finite number,
  validFromHour?: finite number, validToHour?: finite number
}
TariffAssignmentCreateInput = { tariffId: positive integer, connectorId?: nonnegative integer }
TariffAssignmentUpdateInput = { tariffId: positive integer, connectorId: positive integer }

Indata för laddprofiler

ChargingProfileInput = {
  label: string(1..40), locationId: positive integer, stackLevel: nonnegative number,
  purposeId: positive integer, kindId: positive integer,
  recurrencyKindId?: positive integer|null, validFrom?: RFC3339|null,
  validTo?: RFC3339|null, startSchedule?: RFC3339|null,
  rateUnitId: positive integer, minChargingRate?: nonnegative number|null
}
ChargingProfileCreate = ChargingProfileInput & { schedule?: SchedulePeriod[0..256] }
SchedulePeriod = { startPeriod: nonnegative number, limit: nonnegative number, numberOfPhases?: positive integer|null }
ChargingScheduleInput = { rateUnitId: positive integer, periods: SchedulePeriod[1..256] }
ProfileAssignmentInput = { profileId: positive integer, connectorId?: nonnegative integer }

Användarindata

UserCreate = { email: email(max 255), name: string(1..255) }
InvitationInput = {
  email: email, name?: string|null, rfid?: string|null,
  allChargers?: boolean, chargerIds?: unique positive integer[0..500]
} // chargerIds must be non-empty unless allChargers=true
AccessInput = { allChargers?: boolean, chargerIds?: unique positive integer[0..500] }
LimitCreate = { limitTypeId: positive integer, energyValue?: nonnegative integer = 0, timeValue?: nonnegative integer = 0 }
LimitPatch = { limitTypeId?: positive integer, energyValue?: nonnegative integer, timeValue?: nonnegative integer }

Minst ett av energyValue eller timeValue måste vara större än noll när en gräns skapas. Inledande och avslutande blanksteg tas bort från e-postadresser och bokstäverna görs gemena. RFID-UID:n accepteras endast vid skrivning och maskeras i lässvar.

Sammanfattning av svars-DTO:er

Endpointtabellerna visar varje svarsomslutning på översta nivån. Detta är de viktigaste återanvändbara DTO:erna i omslutningarna:

DTOFält
Workspaceid, name, email, website, address { line1, line2, postalCode, city, state, countryId, countryCode, countryName }, createdAt, updatedAt
Siteid, name, description, address, timezone { id, name }, latitude, longitude, chargerCount; detalj lägger till normaliserade chargers och kontakttillstånd
GeocodeCandidateplaceId, displayName, latitude, longitude; leverantörsuppgifter och leverantörsspecifika metadata returneras aldrig
MetricsWindowfrom, to, sessionsgränser/-antal och totalsCapped där det är tillämpligt
Chargerid, name, identifier, cpoId, site, normaliserad status, isPublic, RFID-/smart-/automatiseringsflaggor, provisioned, connection, evses, connectors, createdAt, updatedAt; detalj lägger till configuration med känsliga värden dolda, firmware och antal
ConnectorportId, connectorId, kontaktuppslags-ID:n, maxVoltage, maxAmperage, maxElectricPower
ReportSessionid, laddare/plats, port- och kontakt-ID:n, minimerade användaruppgifter, active, energyWh, start/stopp/varaktighet samt netto-/skatte-/totalkostnad per valuta
ReportScheduleid, workspaceId, enabled, recipientEmail, format, UTC sendDay/sendTime, metadata för skapande/uppdatering och säkra metadata för senaste leverans inklusive antal försök
Tariffid, cpoId, name, objekt för typ/plats/valuta/elområde, tax, fallbackPrice, effektiv price, components, assignmentCount
ChargingProfileid, cpoId, label, description, stackLevel, objekt för placering/syfte/typ/återkomst/laddningsenhet, giltighet, schema, assignmentCount, tidsstämplar
Userid, membershipId, name, email, maskerade rfids, laddarens access, limitCount; detalj lägger till phone, createdAt och limits. OCPP-auktoriseringsuppgifter som contractId returneras aldrig.
RFIDid, maskedUid, name, type, valid; rått UID returneras aldrig
AccessallChargers, sorterade chargerIds och items med metadata för åtkomst/laddare/plats/utgång
Limitid, limitTypeId, label, energyValue, timeValue
LocalUserList-DTO: id, customerId, name, email, expiresAt, systemManaged. Ändringar av lokala användare använder de separata strukturerna LocalUserMutation/LocalUserUpdate i Scheman och exempel.

Uppslagsobjekt returneras av list- och detaljrutter så att klienter kan hitta giltiga ID:n. Behandla okända nytillkomna fält som framåtkompatibla och basera logiken enbart på dokumenterade stabila fält och felkoder.

Arbetsyteendpoints

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/adminworkspaces:readKropp: ingen200 { workspace: Workspace }
PATCH /v2/adminworkspaces:updateKropp: WorkspacePatch200 { workspace: Workspace }
GET /v2/admin/dashboardworkspaces:read + reports:readKropp/fråga: ingen200 { window, stats { chargerCount, onlineChargerCount, siteCount, userCount }, sessions: DashboardSession[], analytics }; sessioner begränsas till 1 000 under 90 dagar

Endpoints för platser och effektstyrning

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/admin/sitessites:readKropp/fråga: ingen200 { items: Site[], metricsWindow: MetricsWindow, lookups { countries, timezones } }
GET /v2/admin/sites/geocodesites:readFråga: valfria street (högst 160), city, state, country (högst 100 vardera), countryCode (högst 2); valfri Accept-Language-header; minst två tecken sammanlagt i gata/stad/region krävs200 { results: GeocodeCandidate[] }; identiska pågående sökningar slås samman och leverantörsarbetet använder en begränsad seriell kö samt en begränsad servercache; ogiltiga sökningar returnerar 400 INVALID_GEOCODE_QUERY, full kö returnerar 429 GEOCODING_BUSY med Retry-After och leverantörsfel returnerar 502 GEOCODING_UNAVAILABLE
POST /v2/admin/sitessites:createKropp: SiteInput201 { site: Site }
GET /v2/admin/sites/:siteIdsites:read + reports:readKropp/fråga: ingen200 { site: SiteDetail, recentSessions: SiteSession[], totals, metricsWindow }
PATCH /v2/admin/sites/:siteIdsites:updateKropp: fullständig SiteInput200 { site: Site }
DELETE /v2/admin/sites/:siteIdsites:deleteKropp: ingen204 empty; en plats som inte är tom returnerar 409 SITE_NOT_EMPTY
GET /v2/admin/sites/:siteId/power-managementsites:power-managementKropp/fråga: ingen200 { configuration: PowerConfiguration } med egen plats, laddare/kontakter, grupper, mätarkällor, tilldelningar och kompatibilitetstillstånd
PUT /v2/admin/sites/:siteId/power-managementsites:power-managementKropp: PowerConfigurationInput200 { configuration: PowerConfiguration }; OCPP-avslag, timeout eller samtidig ändring returnerar 409 POWER_MANAGEMENT_CONFLICT utan att ersättningen tillämpas

Laddarendpoints

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/admin/chargerschargers:readKropp/fråga: ingen200 { items: Charger[], metricsWindow: MetricsWindow, connectorLookups { formats, types, powerTypes } }
POST /v2/admin/chargerschargers:createKropp: ChargerCreate; identifieraren görs till versaler201 { charger: Charger }; lösenordet returneras aldrig
GET /v2/admin/chargers/:chargerIdchargers:readKropp/fråga: ingen200 { charger: ChargerDetail }
PATCH /v2/admin/chargers/:chargerIdchargers:updateKropp: ChargerPatch200 { charger: ChargerDetail }
DELETE /v2/admin/chargers/:chargerIdchargers:deleteKropp: ingen204 empty
PATCH /v2/admin/chargers/:chargerId/credentialschargers:credentialsKropp: { password: string(0..40) }200 { success: true }
PATCH /v2/admin/chargers/:chargerId/connectors/:portIdchargers:connector-settingsKropp: ConnectorPatch200 { connector: Connector }
PATCH /v2/admin/chargers/:chargerId/public-listingchargers:publicKropp: { isPublic: boolean }200 { isPublic: boolean }; bristande beredskap returnerar 409 CHARGER_CONFLICT
GET /v2/admin/chargers/:chargerId/public-readinesschargers:readKropp/fråga: ingen200 { readiness: { ready, missingRequirements, connectorIds, missingTariffConnectorIds, ...commercialState } }
GET /v2/admin/chargers/:chargerId/logschargers:readFråga: cursor?, limit?=50 (1..200), from?, to?, action?, direction?, levelId?200 { items: RedactedOcppLog[], nextCursor: number or null }
GET /v2/admin/chargers/:chargerId/sessionschargers:read + reports:readFråga: page?=1, limit?=25 (1..100), from?, to?, customerId?: positive integer or "unknown"200 { items: ChargerSession[], pagination { page, limit, total, totalPages }, filters { customers }, totals, totalsCapped }
GET /v2/admin/chargers/:chargerId/qrchargers:readFråga: connector?: integer[0,255]200 image/png-binärdata, 300 px, Content-Disposition: inline, Cache-Control: no-store
GET /v2/admin/chargers/:chargerId/composite-scheduleschargers:readFråga: cursor?, limit?=20 (1..50), connectorId?200 { items: CompositeSchedule[], nextCursor: number or null }
GET /v2/admin/chargers/:chargerId/configurationchargers:readKropp/fråga: ingen200 { items: ChargerConfiguration[] }; värden av hemlig karaktär är [REDACTED]
PATCH /v2/admin/chargers/:chargerId/configurationchargers:configurationKropp: { key: string(1..50), value: string(0..500) }200 { status: string }, där status är laddarens/OCPP-resultatet
POST /v2/admin/chargers/:chargerId/configuration/reloadchargers:configurationKropp: ingen200 { status: string }
GET /v2/admin/chargers/:chargerId/firmwarechargers:readKropp/fråga: ingen200 { firmware: { status, notifiedAt, currentVersion, bootNotifiedAt } }
POST /v2/admin/chargers/:chargerId/firmwarechargers:firmwareKropp: { url: HTTP-or-HTTPS URL, max 2048 characters }202 { status: string }
POST /v2/admin/chargers/:chargerId/commands/resetchargers:commandsKropp: { resetType: "Soft" or "Hard" }200 { status: string }
POST /v2/admin/chargers/:chargerId/commands/availabilitychargers:commandsKropp: { availabilityType: "Operative" or "Inoperative" }200 { status: string }
POST /v2/admin/chargers/:chargerId/commands/triggerchargers:commandsKropp: { messageType: "BootNotification", "Heartbeat", "StatusNotification", or "MeterValues" }200 { status: string, connectorResults: { connectorId, status }[] }
POST /v2/admin/chargers/:chargerId/commands/unlockchargers:commandsKropp: { connectorId: positive integer }200 { status: string }
POST /v2/admin/chargers/:chargerId/commands/composite-schedulechargers:commandsKropp: { connectorId: nonnegative integer, durationSeconds?: integer[60,604800], chargingRateUnit?: "W" or "A" }200 { status: string, connectorId: number, compositeSchedule: CompositeSchedule or null }

Rapportendpoints

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/admin/reports/datareports:readFråga: ReportFilters, ogenomskinlig cursor?, limit?=50 (1..100)200 { items: ReportSession[], pageTotals, page { limit, nextCursor }, range { from, to, toExclusive: true } }
GET /v2/admin/reports/schedulereports:readKropp/fråga: ingen200 { schedule: ReportSchedule or null }
PUT /v2/admin/reports/schedulereports:schedulesKropp: strikt ReportScheduleInput200 { schedule: ReportSchedule }
POST /v2/admin/reports/sendreports:sendKropp: ingen; headern Idempotency-Key krävs200 { sent: true, format: "csv" or "pdf", rowCount: number, range { from, to } }; inget sparat schema returnerar 409 REPORT_SCHEDULE_REQUIRED
GET /v2/admin/reports/measurementsreports:readFråga: obligatorisk transactionLogId, ogenomskinlig cursor?, limit?=500 (1..1000)200 { transactionLogId, measurements: { name, unit, lines[] }[], page { limit, nextCursor, sampleValuesTruncated, sampleLimitPerMeterValue: 64 } }
GET /v2/admin/reports/exportreports:exportFråga: ReportFilters, format?="csv" or "pdf"200 CSV/PDF-binärdata med bilagans filnamn, Cache-Control: private, no-store, X-Content-Type-Options: nosniff; fler än 2 000 rader returnerar 422 REPORT_EXPORT_ROW_LIMIT

Tariffendpoints

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/admin/tariffstariffs:readKropp/fråga: ingen200 { items: Tariff[], lookups { currencies, biddingZones, currencyRates, componentTypes, seasons, tariffTypes } }
POST /v2/admin/tariffstariffs:createKropp: TariffInput201 { tariff: Tariff }
GET /v2/admin/tariffs/:tariffIdtariffs:readKropp/fråga: ingen200 { tariff: Tariff, lookups }
PATCH /v2/admin/tariffs/:tariffIdtariffs:updateKropp: fullständig TariffInput200 { tariff: Tariff }
PUT /v2/admin/tariffs/:tariffId/componentstariffs:componentsKropp: { components: TariffComponentInput[0..256] }200 { tariff: Tariff, components: TariffComponent[] }
DELETE /v2/admin/tariffs/:tariffIdtariffs:deleteKropp: ingen204 empty; referenser från laddposter returnerar 409 TARIFF_CONFLICT
GET /v2/admin/tariffs/:tariffId/market-pricestariffs:readFråga: obligatorisk startsAt, icke-negativ Unix-tidsstämpel200 { items: { id, value, currencyId, startsAt, endsAt, startsAtIso, endsAtIso, intervalMinutes }[], truncated: boolean }; högst 10 000 rader
GET /v2/admin/chargers/:chargerId/tariff-assignmentschargers:tariff-assignments + tariffs:readKropp/fråga: ingen200 { items: TariffAssignment[], tariffs: Tariff[] }
POST /v2/admin/chargers/:chargerId/tariff-assignmentschargers:tariff-assignments + tariffs:assignKropp: TariffAssignmentCreateInput; utelämnad connectorId eller connectorId=0 betyder alla kontakter201 { assignments: TariffAssignment[] }
PATCH /v2/admin/chargers/:chargerId/tariff-assignments/:assignmentIdchargers:tariff-assignments + tariffs:assignKropp: TariffAssignmentUpdateInput; kontakt krävs och får inte vara 0200 { assignment: TariffAssignment }
DELETE /v2/admin/chargers/:chargerId/tariff-assignments/:assignmentIdchargers:tariff-assignments + tariffs:assignKropp: ingen204 empty

TariffAssignment innehåller id, chargerId, connectorId, en säker tariff-/valutasammanfattning, createdAt och updatedAt.

Endpoints för laddprofiler

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/admin/charging-profileschargingProfiles:readKropp/fråga: ingen200 { items: ChargingProfile[], lookups { locations, purposes, kinds, recurrencyKinds, rateUnits, allowedRateUnits } }
POST /v2/admin/charging-profileschargingProfiles:createKropp: ChargingProfileCreate201 { profile: ChargingProfile }
GET /v2/admin/charging-profiles/:profileIdchargingProfiles:readKropp/fråga: ingen200 { profile: ChargingProfile, lookups, isEditBlocked: boolean, usage { simpleChargingSchedule, smartSchedule, chargePoolChargepoint, isUsed } }
PATCH /v2/admin/charging-profiles/:profileIdchargingProfiles:updateKropp: fullständig ChargingProfileInput200 { profile: ChargingProfile, ocppSync: OcppCommandResult[] }
PUT /v2/admin/charging-profiles/:profileId/schedulechargingProfiles:updateKropp: ChargingScheduleInput200 { profile: ChargingProfile, schedule: SchedulePeriod[], ocppSync: OcppCommandResult[] }
DELETE /v2/admin/charging-profiles/:profileIdchargingProfiles:deleteKropp: ingen204 empty först efter att alla tilldelade laddare accepterat rensning och tillståndet validerats igen; annars 409 och profilen behålls
GET /v2/admin/chargers/:chargerId/profile-assignmentschargers:profile-assignments + chargingProfiles:readKropp/fråga: ingen200 { items: ProfileAssignment[], profiles: ChargingProfile[] }
POST /v2/admin/chargers/:chargerId/profile-assignmentschargers:profile-assignments + chargingProfiles:assignKropp: ProfileAssignmentInput201 { assignment: ProfileAssignment, ocpp: OcppCommandResult }
PATCH /v2/admin/chargers/:chargerId/profile-assignments/:assignmentIdchargers:profile-assignments + chargingProfiles:assignKropp: ProfileAssignmentInput200 { assignment: ProfileAssignment, ocpp: OcppCommandResult }
DELETE /v2/admin/chargers/:chargerId/profile-assignments/:assignmentIdchargers:profile-assignments + chargingProfiles:assignKropp: ingen204 empty efter synkroniserad rensning

ProfileAssignment innehåller tilldelnings-ID, laddar-/kontakt-ID:n och en säker profilsammanfattning. OCPP-resultatobjekt visar stabil anrops- och statusinformation men aldrig autentiseringsuppgifter.

Endpoints för användare, RFID, åtkomst, gränser och lokala användare

Metod och sökvägBehörighetsområdeAnropLyckat svar
GET /v2/admin/usersusers:readFråga: statusanpassad cursor? (members: positiv numerisk; invitations: autentiserad ogenomskinlig i2.*; all: numerisk fortsättning av äldre medlemsström eller autentiserad ogenomskinlig sammansatt a2.*), limit?=50 (1..100), status?="all", "members", or "invitations"; valfri X-Admin-User-Search-header (högst 100)200 { items: User[], invitations: Invitation[], chargers: ChargerSummary[], page { nextCursor, memberNextCursor, invitationNextCursor, limit } }; inbjudningar sidindelas och fylls med samma normaliserade e-postuttryck så att äldre användning av versaler/gemener eller blanksteg inte kan dölja rader; markörer är bundna till arbetsyta och sökfilter, innehåller ingen läsbar e-postadress och måste returneras oförändrade; all-markörer för medlems- och inbjudningsströmmar framåt oberoende av varandra
POST /v2/admin/usersusers:createKropp: UserCreate; kunden måste redan vara registrerad201 { user: User }; en okänd e-postadress returnerar 404 RESOURCE_NOT_FOUND-kroppen utan att avslöja resursens existens och bör använda inbjudningar
POST /v2/admin/users/invitationsusers:invitations + users:access; samt users:rfid om rfid angesKropp: InvitationInput200 or 201 { result }; kopplat resultat är { kind:"attached", user, accessChanged, rfidChanged }; väntande resultat är { kind:"invited", email, name, maskedRfid, chargerIds, createdCount, emailSent, emailRetryReady, alreadyInvited }
POST /v2/admin/users/invitations/resendusers:invitationsKropp: { email: email }200 { result: { targetedChargers, emailSent, emailRetryReady } }; mottagarövergripande väntetid tillämpas
DELETE /v2/admin/users/invitationsusers:invitationsKropp: { email: email }204 empty
GET /v2/admin/users/:userIdusers:read + reports:readKropp/fråga: ingen200 { user: UserDetail, sessions: UserSession[], totals { count, energyWh, durationSeconds }, window, limitTypes, chargers }; högst 200 sessioner under 90 dagar
PATCH /v2/admin/users/:userIdusers:updateKropp: { name: string(1..255) }200 { user: User }
DELETE /v2/admin/users/:userIdusers:deleteKropp: ingen204 empty
GET /v2/admin/users/:userId/vehiclesusers:readFråga: numerisk cursor?, limit?=50 (1..100)200 { items: Vehicle[], page { nextCursor, limit } }; fordons-DTO:n innehåller säkra fält för leverantör/status/modell/telemetri
GET /v2/admin/users/:userId/rfidsusers:readKropp/fråga: ingen200 { items: RFID[] }; UID:n maskeras
POST /v2/admin/users/:userId/rfidsusers:rfidKropp: { uid: string(1..36), name?: string or null }201 { rfid: RFID }; rått UID returneras inte
PATCH /v2/admin/users/:userId/rfids/:rfidIdusers:rfidKropp: { name: string or null }200 { rfid: RFID }
DELETE /v2/admin/users/:userId/rfids/:rfidIdusers:rfidKropp: ingen204 empty
GET /v2/admin/users/:userId/accessusers:readKropp/fråga: ingen200 { access: Access }
PUT /v2/admin/users/:userId/accessusers:accessKropp: AccessInput200 { access: Access }
DELETE /v2/admin/users/:userId/access/:accessIdusers:accessKropp: ingen204 empty
GET /v2/admin/users/:userId/limitsusers:readKropp/fråga: ingen200 { items: Limit[] }
POST /v2/admin/users/:userId/limitsusers:limitsKropp: LimitCreate201 { limit: Limit }
PATCH /v2/admin/users/:userId/limits/:limitIdusers:limitsKropp: LimitPatch, minst en egenskap200 { limit: Limit }
DELETE /v2/admin/users/:userId/limits/:limitIdusers:limitsKropp: ingen204 empty
GET /v2/admin/chargers/:chargerId/local-userschargers:read + users:readKropp/fråga: ingen200 { charger: ChargerSummary, items: LocalUser[], invitations: { email }[], availableMembers: [] }; API:et utelämnar avsiktligt portalens breda katalog över tillgängliga medlemmar
POST /v2/admin/chargers/:chargerId/local-userschargers:local-users + users:accessKropp: { customerId: positive integer, expiresAt?: RFC3339 or null }201 { localUser: LocalUserMutation }
POST /v2/admin/chargers/:chargerId/local-users/invitationschargers:local-users + users:invitations + users:accessKropp: { email: email }200 or 201 { result }; befintlig kund: { invited:false, localUser: LocalUserMutation }; inbjudan: { invited:true, alreadyInvited, emailSent, emailRetryReady }
DELETE /v2/admin/chargers/:chargerId/local-users/invitationschargers:local-users + users:invitationsKropp: { email: email }204 empty
PATCH /v2/admin/chargers/:chargerId/local-users/:localUserIdchargers:local-users + users:accessKropp: { expiresAt: RFC3339 or null }200 { localUser: LocalUserUpdate }
DELETE /v2/admin/chargers/:chargerId/local-users/:localUserIdchargers:local-users + users:accessKropp: ingen204 empty

Tagless-systemanvändaren skyddas från dessa åtgärder. Fel vid inbjudningsmejl returnerar ett säkert leveranstillstånd utan att läcka SMTP-uppgifter; klienter kan försöka igen när emailRetryReady är sant.

Binära svar

Två endpointgrupper returnerar inte JSON vid framgång:

EndpointInnehållstypViktiga headrar
Laddarens QR-kodimage/pngCache-Control: no-store, Content-Disposition: inline, X-Content-Type-Options: nosniff
Rapportexporttext/csv; charset=utf-8 eller application/pdfCache-Control: private, no-store, Content-Disposition: attachment, X-Content-Type-Options: nosniff

Fel från binära endpoints är fortfarande JSON.