{"openapi":"3.1.0","info":{"title":"Ivora Platform API","description":"The internal Ivora API for tenant charger management, charging, billing and payment adapters.\n**Environment: production (`.com`). Stripe payments are live.**\n\n### Start here\n\n1. Open [Developer tools](https://platform.ivoracharge.com/developer). Your CSMS tenant comes from the access grant Ivora assigned to your account. Create a key with the scopes your application needs; station and billing keys bind to your tenant automatically.\n2. Send the key from your server as `Authorization: Bearer iv_live_…`. A Supabase access token also works.\n3. Call `GET /v1/access` (under **Access and API keys** in the API reference, or from the portal's Try it console), then use your tenant ID in the station, billing and payment routes. For onboarding outside Developer tools, call `POST /v1/me/tenant` with your signed-in Supabase access token first. Repeating this call returns the same assignment. Existing CSMS grants retain their current permissions.\n4. The [API reference](https://ivoracharge.com/developers/api) lists each operation's scopes, parameters, responses and samples.\n\n### Choose a workflow\n\nStart with the [settlement flow comparison](https://ivoracharge.com/developers/guides/settlement)\nand [architecture diagrams](https://ivoracharge.com/developers/guides/getting-started/architecture).\nThe guides distinguish managed payments, application-managed processors,\nexisting driver settlement and free/simulated charging. **External charging sessions**\nallow your backend to integrate its own processor now. Self-service managed-adapter\nregistration remains planned.\n\nBusiness profiles, free-charging eligibility/passwords, QR cards and checkout\npresentation belong to the consuming application and its database. The shared\nAPI handles charger operations, trusted usage and billing support. It also keeps\nthe QR a charger's own screen shows as desired state; your application chooses\nthat URL and serves its page.\n\n| Task | Reference sections | Order of calls |\n| --- | --- | --- |\n| Register a charger | Locations → Stations | Create location → register station (both return the resource) → set connection credentials → read connector state |\n| Show a QR on a charger screen | Stations → Charger displays | Read the station's `display` field → set each EVSE's display → watch `delivery.state` or `display.delivery_changed`; print the QR where the state is `unsupported` |\n| Stop polling | Webhooks and events | Register an HTTPS endpoint → verify the signed test delivery → consume operation, session, bill and display events |\n| Paid charging | Tariffs and bills → Payments → Charging and operations | Create bill → authorize payment → follow checkout → confirm authorization → start bill → observe transaction → stop → finalize bill → capture |\n| Application-managed processor | External charging sessions | Authorize in your backend → create session → attest funding/start → observe/stop → finalize → capture in your backend → optionally report outcome |\n| Release or refund | Payments | Release an unused authorization; refund a captured payment |\n| Try without hardware | Workspaces → Sandbox charging | Create workspace → start a simulated session → advance metering → stop and settle |\n\nFor payment-adapter testing without hardware, create a bill with `source: simulated` and finalize it with `energy_wh`. Physical bills use `source: csms` and a completed `transaction_id`.\n\n### Access, units and retries\n\n- Keep tenant API keys on your application server. Your app controls host/guest permissions and bookings within its granted fleet.\n- Station reads need `stations:read`; provisioning and charger displays need `stations:write`; commands need `stations:control`. Bills and payments use `billing:read` / `billing:write`. Bill start also needs `stations:control`. External session creation/start opts in with `settlement:write`; reporting requires that scope and never executes a payment. Key management requires a signed-in workspace owner.\n- Charging/billing writes that declare **Idempotency-Key** require 8–128 printable characters. Generate a unique key per operation and reuse it with the same body after a timeout.\n- Creating a location, station or tariff returns **201 with the resource and its ID**; add `external_reference` to find it by your own identifier. Charger-bound writes return a **202 operation**: poll it, or subscribe to `operation.completed` under **Webhooks and events**. Reconcile an `unknown` charger outcome before issuing another command. Unknown payment operations older than 23 hours require operator reconciliation.\n- Errors are `{\"error\": {\"code\", \"message\", \"details\"}}` with stable codes such as `station_offline` or `idempotency_key_reused`; rejected operations repeat the shape in `result.error`.\n- Core energy is **kWh** and every energy field also carries integer **`energy_wh`**; sandbox increments are **Wh**; tariff and payment amounts are integer **minor currency units**. Bills fix the tariff and final amount; payment clients cannot choose a different capture amount.\n\nThe Stripe payment adapter takes live USD card payments by direct charge on each tenant's Connect account: authorization, capture, release and full refund. Physical end-to-end acceptance, automatic reconciliation, provider registration and marketplace payouts remain future work.\n\n[Workflow guides](https://ivoracharge.com/developers/guides) · [Architecture plan](https://platform.ivoracharge.com/plan) · [Download OpenAPI](https://api.ivoracharge.com/openapi.json)\n","version":"1.0.0"},"servers":[{"url":"https://api.ivoracharge.com"}],"paths":{"/v1":{"get":{"tags":["Getting started"],"summary":"Discovery","operationId":"discovery_v1_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/health":{"get":{"tags":["Getting started"],"summary":"Health","operationId":"health_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/config":{"get":{"tags":["Getting started"],"summary":"Public Config","operationId":"public_config_v1_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/capabilities":{"get":{"tags":["Getting started"],"summary":"Capabilities","operationId":"capabilities_v1_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/me/tenant":{"post":{"tags":["Access and API keys"],"summary":"Retrieve the charging tenant of your access grant","description":"Developer tools calls this automatically on entry. Requires a signed-in confirmed user, not an API key. Repeated and concurrent calls return the same tenant. Returns the tenant of your access grant without upgrading viewer permissions; accounts without a grant receive 403 and no tenant is created. No caller-supplied tenant ID is accepted.","operationId":"onboard_v1_me_tenant_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantAssignment"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/me":{"get":{"tags":["Workspaces"],"summary":"Me","operationId":"me_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextRecord"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/workspace":{"post":{"tags":["Workspaces"],"summary":"Workspace","operationId":"workspace_v1_workspace_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceRecord"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/branding":{"put":{"tags":["Workspaces"],"summary":"Branding","operationId":"branding_v1_branding_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingInput"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/api-keys":{"get":{"tags":["Access and API keys"],"summary":"Keys","operationId":"keys_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Access and API keys"],"summary":"Create Key","operationId":"create_key_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyInput"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/api-keys/{key_id}":{"delete":{"tags":["Access and API keys"],"summary":"Revoke","operationId":"revoke_v1_api_keys__key_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/access":{"get":{"tags":["Access and API keys"],"summary":"Discover current internal CSMS access","operationId":"context_v1_access_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unprocessable Entity","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Too Many Requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Bad Gateway","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/tenants/{tenant_id}/stations":{"get":{"tags":["Stations"],"summary":"List tenant charging stations","operationId":"stations_v1_tenants__tenant_id__stations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}],"title":"Name"}},{"name":"external_reference","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}],"description":"Return only the resource carrying this external_reference","title":"External Reference"},"description":"Return only the resource carrying this external_reference"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"post":{"tags":["Stations"],"summary":"Register a station and return it","description":"Synchronous: the response is the station with its resource ID, connectors and default connection_url. Idempotency-Key replays return the same station; the journal guarantees one registration per key. A 503 outcome_unknown means the core did not answer: list stations by name or external_reference before retrying with a new key. Registration does not connect hardware; set credentials next.","operationId":"create_station_v1_tenants__tenant_id__stations_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}":{"get":{"tags":["Stations"],"summary":"Read station and connector state","operationId":"station_v1_tenants__tenant_id__stations__station_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"delete":{"tags":["Stations"],"summary":"Delete a station that never charged","description":"Synchronous. Deletes the station, its EVSEs and connectors when it has no transactions; a connected station is disconnected first. Stations with charging history return 409 station_has_history and stay in inventory (detach them in your application instead); an active transaction returns 409 transaction_active. Replays with the same Idempotency-Key return the same result.","operationId":"delete_station_v1_tenants__tenant_id__stations__station_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationDeleted"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"patch":{"tags":["Stations"],"summary":"Move a station to an owned location","operationId":"update_station_v1_tenants__tenant_id__stations__station_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationUpdate"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}/credentials":{"put":{"tags":["Stations"],"summary":"Set the station's OCPP connection password","description":"Offline stations store the password for their next connection (result.applied = stored). Connected OCPP 2.0.1/2.1 stations receive it over OCPP and it is stored once accepted (result.applied = pushed). A connected OCPP 1.6 station is rejected with station_online because the core cannot push its password.","operationId":"password_v1_tenants__tenant_id__stations__station_id__credentials_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordInput"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}/commands":{"post":{"tags":["Charging and operations"],"summary":"Dispatch start, stop, reset, unlock or availability","description":"Start is an operator command and does not authorize payment. For paid charging start an authorized bill. A succeeded operation means the adapter replied; observe dispatch response and transactions for charging. Never resend unknown or dispatching operations with a new key.","operationId":"command_v1_tenants__tenant_id__stations__station_id__commands_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandInput"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/locations":{"get":{"tags":["Locations"],"summary":"List tenant locations","operationId":"locations_v1_tenants__tenant_id__locations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"external_reference","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}],"description":"Return only the resource carrying this external_reference","title":"External Reference"},"description":"Return only the resource carrying this external_reference"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"post":{"tags":["Locations"],"summary":"Create a tenant charging location and return it","description":"Synchronous: the response carries the location resource ID. Replays with the same Idempotency-Key return the same location. Supply external_reference to make the location findable by your own identifier and to prevent duplicates for the same reference.","operationId":"create_location_v1_tenants__tenant_id__locations_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/locations/{location_id}":{"get":{"tags":["Locations"],"summary":"Read one location","operationId":"location_v1_tenants__tenant_id__locations__location_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"location_id","in":"path","required":true,"schema":{"type":"integer","title":"Location Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"patch":{"tags":["Locations"],"summary":"Update a location's details","description":"Synchronous. Changes only the supplied fields; latitude and longitude travel together. Replays with the same Idempotency-Key return the current location.","operationId":"update_location_v1_tenants__tenant_id__locations__location_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"location_id","in":"path","required":true,"schema":{"type":"integer","title":"Location Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/transactions":{"get":{"tags":["Charging and operations"],"summary":"Read charging usage and realized billing","operationId":"transactions_v1_tenants__tenant_id__transactions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Station Id"}},{"name":"external_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"External Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/tariffs":{"get":{"tags":["Tariffs and bills"],"summary":"Read tenant billing tariffs","operationId":"tariffs_v1_tenants__tenant_id__tariffs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"external_reference","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}],"description":"Return only the resource carrying this external_reference","title":"External Reference"},"description":"Return only the resource carrying this external_reference"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TariffList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"post":{"tags":["Tariffs and bills"],"summary":"Create a core tariff version and return it","description":"Synchronous: the response carries the tariff resource ID. Tariffs are immutable versions; create another rather than editing. Historical tariffs and the independent payment catalog are unchanged. Replays with the same Idempotency-Key return the same tariff.","operationId":"create_tariff_v1_tenants__tenant_id__tariffs_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TariffInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TariffRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/tariffs/{tariff_id}":{"get":{"tags":["Tariffs and bills"],"summary":"Read one tariff","operationId":"tariff_v1_tenants__tenant_id__tariffs__tariff_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"tariff_id","in":"path","required":true,"schema":{"type":"integer","title":"Tariff Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TariffRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/operations/{operation_id}":{"get":{"tags":["Charging and operations"],"summary":"Inspect an operation without redispatching it","operationId":"get_operation_v1_tenants__tenant_id__operations__operation_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"operation_id","in":"path","required":true,"schema":{"type":"string","title":"Operation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/payment-services":{"get":{"tags":["Payments"],"summary":"List configured payment adapters","operationId":"services_v1_tenants__tenant_id__payment_services_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/bills":{"post":{"tags":["Tariffs and bills"],"summary":"Snapshot a tariff before charging","description":"Provider-independent bill. Authorize payment, then use the bill start endpoint. Keep its charging_token on the application server. Simulation is explicit and never accepts physical transactions.","operationId":"create_bill_v1_tenants__tenant_id__bills_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"get":{"tags":["Tariffs and bills"],"summary":"List tenant bills","description":"Repository snapshots without usage observation, ordered by opaque bill ID. Filter by station_id and status. Read one bill for its live usage.","operationId":"bills_v1_tenants__tenant_id__bills_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Station Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["open","final"],"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"after","in":"query","required":false,"schema":{"type":"string","maxLength":40,"default":"","title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/bills/{bill_id}":{"get":{"tags":["Tariffs and bills"],"summary":"Read a bill with its usage and start operation","description":"Open physical bills with a dispatched start report the matched transaction as usage (ambiguity fails closed); final bills keep a final usage snapshot. Reads never finalize, dispatch or move money.","operationId":"bill_v1_tenants__tenant_id__bills__bill_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","title":"Bill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/bills/{bill_id}/finalize":{"post":{"tags":["Tariffs and bills"],"summary":"Calculate the final bill from completed charging usage","description":"Physical bills require a matching tenant/station/connector/token and completed CSMS transaction. The API reads kWh and calculates integer cents with final half-up rounding. No amount override; final bills never change. Legacy-settled transactions are refused.","operationId":"finalize_v1_tenants__tenant_id__bills__bill_id__finalize_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","title":"Bill Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalizeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/{service}/v1/tenants/{tenant_id}/payments":{"post":{"tags":["Payments"],"summary":"Create a hosted authorization for a bill","description":"service is stripe or simulator. One payment per bill across providers and keys. The tariff supplies the hold. return_surface selects where hosted checkout returns: the developer sandbox (default) or the driver charging page for the bill's station and connector, with URLs chosen by the API. Retry this request with the same key if the outcome is unknown.","operationId":"authorize_payment__service__v1_tenants__tenant_id__payments_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/{service}/v1/tenants/{tenant_id}/payments/{payment_id}":{"get":{"tags":["Payments"],"summary":"Synchronize payment status with the provider","description":"The tenant's single payment read. Adds processor_reference and the checkout customer_email, which no other response carries.","operationId":"status_payment__service__v1_tenants__tenant_id__payments__payment_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","title":"Payment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentDetail"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/bills/{bill_id}/start":{"post":{"tags":["Charging and operations"],"summary":"Start charging after adapter authorization","description":"Requires billing:write and stations:control. Registers a short-lived charging token, then dispatches once. Poll transactions for actual charging. An unknown operation requires reconciliation, not a new start key. No automatic start is triggered by checkout redirects.","operationId":"start_v1_tenants__tenant_id__bills__bill_id__start_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","title":"Bill Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/{service}/v1/tenants/{tenant_id}/payments/{payment_id}/capture":{"post":{"tags":["Payments"],"summary":"Capture exactly the immutable bill amount","description":"No amount body. Over-hold bills are rejected with bill_exceeds_hold (and an operator alert) rather than silently undercharged. Zero bills release the hold, and so does the Stripe adapter for bills below Stripe's 50-cent minimum charge, which it cannot collect: the payment ends canceled with captured_minor 0. Use the same payment ID and idempotency key on retry.","operationId":"capture_payment__service__v1_tenants__tenant_id__payments__payment_id__capture_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","title":"Payment Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/{service}/v1/tenants/{tenant_id}/payments/{payment_id}/release":{"post":{"tags":["Payments"],"summary":"Release an unused authorization","description":"Does not stop a charger. The application must stop/reconcile charging separately before releasing payment. After a dispatched start, release is allowed only once the 15-minute charging token has expired (20 minutes after dispatch) and no transaction matches the bill; otherwise start_reserved is returned.","operationId":"release_payment__service__v1_tenants__tenant_id__payments__payment_id__release_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","title":"Payment Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/{service}/v1/tenants/{tenant_id}/payments/{payment_id}/refund":{"post":{"tags":["Payments"],"summary":"Refund the full captured amount","description":"Requires billing:refund. One full refund per payment. Pending refunds are reconciled by reading status. Partial refunds and Connect payouts are outside this initial adapter.","operationId":"refund_payment__service__v1_tenants__tenant_id__payments__payment_id__refund_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"service","in":"path","required":true,"schema":{"type":"string","title":"Service"}},{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","title":"Payment Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/billing/bills/{bill_id}/alerts":{"post":{"tags":["Tariffs and bills"],"summary":"Record a billing alert for a bill","description":"Requires billing:write on the bill's tenant. kind hold_stop: the application stopped charging because usage neared the hold. Recorded once per bill and kind; repeating the call returns the same alert. Alerts never move money.","operationId":"alert_v1_billing_bills__bill_id__alerts_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"bill_id","in":"path","required":true,"schema":{"type":"string","pattern":"^bill_[0-9a-f]{32}$","title":"Bill Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/stripe/v1/tenants/{tenant_id}/account":{"get":{"tags":["Payment account"],"summary":"Read the tenant's payment account","description":"Requires billing:read. The provider's pinned Stripe Connect account with its live readiness (charges_enabled, requirements). status none means no account; pending_review means onboarded and awaiting Ivora approval before it can take payments.","operationId":"status_payment_stripe_v1_tenants__tenant_id__account_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentAccountRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/stripe/v1/tenants/{tenant_id}/account/onboarding-link":{"post":{"tags":["Payment account"],"summary":"Create a Stripe onboarding link","description":"Signed-in tenant-admin or Ivora staff; API keys are refused. The return page is server-selected by portal. A pinned account gets a new link for the same account; a tenant without one gets a new Standard account. A tenant whose legacy records already name an account gets payment_account_requires_staff_pin. Links are single-use: an identical retry returns a fresh link.","operationId":"onboarding_payment_stripe_v1_tenants__tenant_id__account_onboarding_link_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Onboarding","default":{"portal":"analytics"}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingLinkRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/payment/stripe/v1/tenants/{tenant_id}/account/disconnect":{"post":{"tags":["Payment account"],"summary":"Disconnect the tenant's payment account","description":"Signed-in tenant-admin or Ivora staff; API keys are refused. New payments then get payment_account_required; payments already authorized keep settling on the account they were authorized on. The Stripe account itself is not changed.","operationId":"disconnect_payment_stripe_v1_tenants__tenant_id__account_disconnect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentAccountRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions":{"post":{"tags":["External charging sessions"],"summary":"Create an externally funded charging session","description":"Requires billing:write and settlement:write. Atomically snapshots the tariff and fixes external settlement ownership. Your backend owns checkout, processor credentials and capture. References contain no secrets. One open physical external session per connector; this does not reserve hardware against other CSMS commands.","operationId":"create_v1_tenants__tenant_id__charging_sessions_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalSessionInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalSessionRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"get":{"tags":["External charging sessions"],"summary":"Find externally funded sessions","description":"Repository snapshots only, without hardware reads. Follow GET by session ID for live usage. A stable application_reference recovers a session after a lost creation response. Cursors order by opaque session ID, not time.","operationId":"sessions_v1_tenants__tenant_id__charging_sessions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"string","maxLength":36,"default":"","title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"application_reference","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Application Reference"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalSessionList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions/{session_id}":{"get":{"tags":["External charging sessions"],"summary":"Observe session usage, bill and reported settlement","description":"Requires billing:read. Correlates live transactions by tenant, station, connector and private charging token. Reads never dispatch commands, finalize a bill or move money. Multiple matches fail closed. A completed bill stays readable if CSMS is unavailable.","operationId":"session_v1_tenants__tenant_id__charging_sessions__session_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalSessionRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions/{session_id}/start":{"post":{"tags":["External charging sessions"],"summary":"Start using application-confirmed funding","description":"Requires billing:write, stations:control and settlement:write. funding_confirmed is an application assertion, not verification by Ivora. Registers a 15-minute token and dispatches at most once per session. Poll session state; successful dispatch is not physical start. No automatic stop at the external hold amount.","operationId":"start_v1_tenants__tenant_id__charging_sessions__session_id__start_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalStartInput"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions/{session_id}/stop":{"post":{"tags":["External charging sessions"],"summary":"Stop the transaction belonging to this session","description":"Requires billing:write and stations:control. Never accepts an arbitrary transaction ID. Unknown or rejected attempts after reservation require operator reconciliation; another key cannot dispatch twice.","operationId":"stop_v1_tenants__tenant_id__charging_sessions__session_id__stop_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions/{session_id}/finalize":{"post":{"tags":["External charging sessions"],"summary":"Finalize trusted usage for external capture","description":"Requires billing:write. Physical usage requires the completed transaction ID observed on the session; simulated sessions require energy_wh. The result is immutable USD cents. Capture it in your backend; Ivora does not call your processor.","operationId":"finalize_v1_tenants__tenant_id__charging_sessions__session_id__finalize_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalizeInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BillRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions/{session_id}/cancel":{"post":{"tags":["External charging sessions"],"summary":"Cancel a session before any start reservation","description":"Requires billing:write. Does not release funds. Once start is reserved, a timeout or absent transaction is insufficient evidence to cancel; reconcile the charger and finalize actual usage.","operationId":"cancel_v1_tenants__tenant_id__charging_sessions__session_id__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalSessionRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/charging-sessions/{session_id}/settlement-reports":{"post":{"tags":["External charging sessions"],"summary":"Record an external processor outcome without moving money","description":"Requires settlement:write. Application-reported, never independently verified. Append-only provenance and operation-reference deduplication. Pending/unknown can resolve once to succeeded/failed; terminal results and amounts cannot change. Successful captures cannot exceed the final bill; refunds cannot exceed successful captures. No processor webhooks are accepted directly.","operationId":"add_report_v1_tenants__tenant_id__charging_sessions__session_id__settlement_reports_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlementReportInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlementReportRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"get":{"tags":["External charging sessions"],"summary":"Read the external settlement audit trail","operationId":"reports_v1_tenants__tenant_id__charging_sessions__session_id__settlement_reports_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettlementReportList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/ocpp-domains":{"get":{"tags":["OCPP domains"],"summary":"List custom OCPP hostnames and DNS/TLS readiness","operationId":"listing_v1_tenants__tenant_id__ocpp_domains_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"post":{"tags":["OCPP domains"],"summary":"Prepare a tenant OCPP domain and its two DNS records","description":"Idempotent by tenant and normalized hostname. Recreating a disabled hostname rotates its ownership challenge. Does not modify DNS or activate TLS.","operationId":"create_v1_tenants__tenant_id__ocpp_domains_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/ocpp-domains/{domain_id}":{"get":{"tags":["OCPP domains"],"summary":"Read one OCPP domain setup","operationId":"get_v1_tenants__tenant_id__ocpp_domains__domain_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"delete":{"tags":["OCPP domains"],"summary":"Disable this domain for new charger connections","description":"Existing WebSocket connections are not forcibly disconnected. DNS records remain in the customer account.","operationId":"disable_v1_tenants__tenant_id__ocpp_domains__domain_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/ocpp-domains/{domain_id}/setup-link":{"post":{"tags":["OCPP domains"],"summary":"Prepare DNS-provider sign-in with Domain Connect","description":"Returns a signed provider approval URL only when the reviewed template and signing key are available. Otherwise returns manual-setup instructions. Never collects DNS credentials.","operationId":"connect_v1_tenants__tenant_id__ocpp_domains__domain_id__setup_link_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupLink"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/ocpp-domains/{domain_id}/verify":{"post":{"tags":["OCPP domains"],"summary":"Check public DNS ownership and direct routing","description":"DNS verification does not mean TLS is active. An edge deployment must succeed before ready becomes true.","operationId":"verify_v1_tenants__tenant_id__ocpp_domains__domain_id__verify_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/webhooks":{"post":{"tags":["Webhooks and events"],"summary":"Register an HTTPS endpoint for tenant events","description":"Requires webhooks:write plus the read scope of each subscribed event type. The signing secret is returned once. Deliveries are signed (Ivora-Signature: t=<unix>,v1=<hex HMAC-SHA256 of '<t>.<body>'>), retried with backoff for about a day and are at-least-once: deduplicate by event id. Subscriptions belong to the tenant and outlive the creating key until disabled.","operationId":"create_v1_tenants__tenant_id__webhooks_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookInput"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"get":{"tags":["Webhooks and events"],"summary":"List webhook endpoints","operationId":"listing_v1_tenants__tenant_id__webhooks_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/webhooks/{webhook_id}":{"get":{"tags":["Webhooks and events"],"summary":"Read one webhook endpoint","operationId":"get_v1_tenants__tenant_id__webhooks__webhook_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"delete":{"tags":["Webhooks and events"],"summary":"Disable a webhook endpoint","description":"Pending deliveries are marked failed. The delivery history stays readable.","operationId":"disable_v1_tenants__tenant_id__webhooks__webhook_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/webhooks/{webhook_id}/test":{"post":{"tags":["Webhooks and events"],"summary":"Queue a signed webhook.test delivery","description":"Delivers only to this endpoint regardless of its subscriptions. Use it to verify signature handling before relying on live events.","operationId":"test_v1_tenants__tenant_id__webhooks__webhook_id__test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestResult"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/webhooks/{webhook_id}/deliveries":{"get":{"tags":["Webhooks and events"],"summary":"Read delivery attempts for an endpoint","operationId":"deliveries_v1_tenants__tenant_id__webhooks__webhook_id__deliveries_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Event sequence cursor","default":0,"title":"After"},"description":"Event sequence cursor"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/events":{"get":{"tags":["Webhooks and events"],"summary":"Poll tenant events by cursor","description":"The same events webhooks deliver, in ascending sequence, for recovery or polling. Requires stations:read; events carrying billing data appear only when the key also has billing:read. Persist next_cursor after processing. Filter by type and, for charger events, by station_id. Webhook filters (stations, meter sample interval) apply to deliveries only: the log keeps every meter.sampled event, at most one per transaction every 10 seconds, for 7 days.","operationId":"events_v1_tenants__tenant_id__events_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"after","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Type"}},{"name":"station_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"description":"Charger events of this station resource ID only","title":"Station Id"},"description":"Charger events of this station resource ID only"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantEventList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}/displays":{"get":{"tags":["Charger displays"],"summary":"List a station's charger displays","description":"Desired state and delivery for every EVSE with a display, from Ivora's repository without a charger read.","operationId":"listing_v1_tenants__tenant_id__stations__station_id__displays_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}/evses/{evse_number}/display":{"put":{"tags":["Charger displays"],"summary":"Set the QR a charger screen shows","description":"Synchronous desired state: returns immediately with delivery.state pending and never waits for the charger. Ivora pushes it on the next sweep, even while an earlier failed push is backing off, and again after reboots and price changes; applied means the charging core accepted the push. The price comes from tariff_id when you set it (a tariff in this tenant, usually the one your application bills with; 404 tariff_not_found otherwise), else from the EVSE's connector tariff; without either, adapters that always carry a price (RCD/Renova) show 0. The same body keeps its revision; any change is a new revision. unsupported means no adapter drives this charger's screen, so use a printed QR. Replays with the same Idempotency-Key return the original result.","operationId":"put_v1_tenants__tenant_id__stations__station_id__evses__evse_number__display_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"evse_number","in":"path","required":true,"schema":{"type":"integer","maximum":99,"exclusiveMinimum":0,"description":"OCPP EVSE number on the station, as in connectors[].evse_number","title":"Evse Number"},"description":"OCPP EVSE number on the station, as in connectors[].evse_number"},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"get":{"tags":["Charger displays"],"summary":"Read a charger display and its delivery","operationId":"get_v1_tenants__tenant_id__stations__station_id__evses__evse_number__display_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"evse_number","in":"path","required":true,"schema":{"type":"integer","maximum":99,"exclusiveMinimum":0,"description":"OCPP EVSE number on the station, as in connectors[].evse_number","title":"Evse Number"},"description":"OCPP EVSE number on the station, as in connectors[].evse_number"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"delete":{"tags":["Charger displays"],"summary":"Stop maintaining a charger display","description":"Returns the final record with deleted true. An adapter that can clear takes a shown QR off the screen first. With clear false the QR stays (delivery.shown keeps the last push: true once a QR was sent, null if none was): RCD/Renova chargers keep it until they reboot, Sinexcel chargers until it is overwritten, because their configuration keys persist. To point a screen elsewhere, set a new qr instead. Replays with the same Idempotency-Key return the original result.","operationId":"delete_v1_tenants__tenant_id__stations__station_id__evses__evse_number__display_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"evse_number","in":"path","required":true,"schema":{"type":"integer","maximum":99,"exclusiveMinimum":0,"description":"OCPP EVSE number on the station, as in connectors[].evse_number","title":"Evse Number"},"description":"OCPP EVSE number on the station, as in connectors[].evse_number"},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisplayRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}/running-cost":{"get":{"tags":["Charger displays"],"summary":"Read a station's running cost setting and deliveries","description":"enabled is true by default (source default) and follows an explicit choice once one is written (source manual, with updated_by and updated_at). support says how this charger's protocol receives cost: OCPP 1.6 by the Open Charge Alliance California Pricing DataTransfer (org.openchargealliance.costmsg RunningCost and FinalCost), OCPP 2.x by CostUpdated where this environment enables it, or charger_rejected when the charger refused the DataTransfer (rejection has its status and time). sessions lists the latest priced bills on the station with what the charging core accepted, and is null without billing:read.","operationId":"get_v1_tenants__tenant_id__stations__station_id__running_cost_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningCostRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}},"put":{"tags":["Charger displays"],"summary":"Switch running cost messages for a station on or off","description":"On by default for every station; this stores an explicit choice that always wins over the default and persists until changed. When enabled, Ivora sends each bill started through this API its running cost while it charges (energy × the bill's rate, as finalization rounds it, at most every interval_seconds and only when it changed) and, on OCPP 1.6, its final cost once after it ends. Sessions without an Ivora bill get no message. Returns at once; the sweep sends. The charger must support the California Pricing extension (OCPP 1.6 CustomDisplayCostAndPrice) or CostUpdated; an OCPP 1.6 charger that rejects it reads charger_rejected and gets nothing until it reboots, and any write here clears that so the next session tries again. Replays with the same Idempotency-Key return the original result.","operationId":"put_v1_tenants__tenant_id__stations__station_id__running_cost_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"idempotency-key","in":"header","required":true,"schema":{"type":"string","title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningCostInput"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningCostRecord"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}},"/v1/tenants/{tenant_id}/stations/{station_id}/faults":{"get":{"tags":["Stations"],"summary":"List a station's open and recent faults","description":"Faults Ivora observed in the charger's status notifications (an OCPP 1.6 errorCode other than NoError, or status Faulted), newest first. A fault stays open until a later notification for the same connector clears it; the station.fault_opened and station.fault_cleared events carry the same id. open=true returns open faults only. Cleared faults are kept for 90 days.","operationId":"faults_v1_tenants__tenant_id__stations__station_id__faults_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tenant_id","in":"path","required":true,"schema":{"type":"integer","title":"Tenant Id"}},{"name":"station_id","in":"path","required":true,"schema":{"type":"integer","title":"Station Id"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"description":"next_cursor of the previous page","title":"Before"},"description":"next_cursor of the previous page"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"open","in":"query","required":false,"schema":{"type":"boolean","description":"Only faults that are still open","default":false,"title":"Open"},"description":"Only faults that are still open"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaultList"}}}},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not Found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unprocessable Entity"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Too Many Requests"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Bad Gateway"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Service Unavailable"}}}}},"components":{"schemas":{"AlertInput":{"properties":{"kind":{"type":"string","const":"hold_stop","title":"Kind","description":"hold_stop: the application stopped charging near the authorization hold. Recorded once per bill."}},"additionalProperties":false,"type":"object","required":["kind"],"title":"AlertInput"},"AlertRecord":{"properties":{"id":{"type":"string","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"bill_id":{"type":"string","title":"Bill Id"},"payment_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Id"},"kind":{"type":"string","enum":["over_hold","near_hold","hold_stop"],"title":"Kind"},"total_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Minor"},"hold_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Hold Minor"},"created_at":{"type":"string","title":"Created At"},"resolved_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved At"}},"type":"object","required":["id","tenant_id","bill_id","payment_id","kind","total_minor","hold_minor","created_at","resolved_at"],"title":"AlertRecord"},"BillInput":{"properties":{"station_id":{"type":"integer","exclusiveMinimum":0,"title":"Station Id"},"connector_id":{"type":"integer","exclusiveMinimum":0,"title":"Connector Id"},"tariff_id":{"type":"integer","exclusiveMinimum":0,"title":"Tariff Id","description":"Tenant-owned tariff, snapshotted before charging"},"source":{"type":"string","enum":["csms","simulated"],"title":"Source","default":"csms"}},"additionalProperties":false,"type":"object","required":["station_id","connector_id","tariff_id"],"title":"BillInput"},"BillList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/BillRecord"},"type":"array","title":"Data"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"BillList"},"BillRecord":{"properties":{"id":{"type":"string","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"station_id":{"type":"integer","title":"Station Id"},"connector_id":{"type":"integer","title":"Connector Id"},"source":{"type":"string","enum":["csms","simulated"],"title":"Source"},"tariff_id":{"type":"integer","title":"Tariff Id"},"rate_minor":{"type":"string","title":"Rate Minor"},"hold_minor":{"type":"integer","title":"Hold Minor"},"currency":{"type":"string","const":"USD","title":"Currency"},"charging_token":{"type":"string","title":"Charging Token"},"status":{"type":"string","enum":["open","final"],"title":"Status"},"energy_kwh":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Energy Kwh"},"energy_wh":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Energy Wh","description":"Integer Wh of the finalized usage."},"total_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Minor"},"transaction_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transaction Id"},"created_at":{"type":"string","title":"Created At"},"finalized_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finalized At"},"settlement_owner":{"type":"string","enum":["managed","external"],"title":"Settlement Owner","default":"managed"},"billing_version":{"type":"string","const":"energy-v1","title":"Billing Version","default":"energy-v1"},"usage":{"anyOf":[{"$ref":"#/components/schemas/UsageRecord"},{"type":"null"}],"description":"Single bill reads only: live matched usage after start, a final snapshot once final."},"start_operation":{"anyOf":[{"$ref":"#/components/schemas/OperationRecord"},{"type":"null"}],"description":"Single bill reads only: the journaled start dispatch, if any."}},"type":"object","required":["id","tenant_id","station_id","connector_id","source","tariff_id","rate_minor","hold_minor","currency","charging_token","status","energy_kwh","total_minor","transaction_id","created_at","finalized_at"],"title":"BillRecord"},"BrandingInput":{"properties":{"name":{"type":"string","maxLength":80,"minLength":2,"title":"Name"},"color":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$","title":"Color"}},"additionalProperties":false,"type":"object","required":["name","color"],"title":"BrandingInput"},"CommandInput":{"properties":{"action":{"type":"string","enum":["start","stop","reset","unlock","availability"],"title":"Action"},"connector_id":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Connector Id","description":"Connector resource ID returned by the station API, not an OCPP connector number"},"transaction_id":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Transaction Id","description":"Transaction resource ID returned by the transactions API"},"token":{"anyOf":[{"type":"string","maxLength":20,"minLength":1},{"type":"null"}],"title":"Token"},"token_type":{"anyOf":[{"type":"string","enum":["Central","eMAID","ISO14443","ISO15693","KeyCode","Local","MacAddress","NoAuthorization"]},{"type":"null"}],"title":"Token Type"},"mode":{"anyOf":[{"type":"string","enum":["soft","hard","operative","inoperative"]},{"type":"null"}],"title":"Mode"}},"additionalProperties":false,"type":"object","required":["action"],"title":"CommandInput"},"ConnectProfile":{"properties":{"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"support_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Support Email"},"support_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Support Phone"},"address_line1":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Line1"},"address_line2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Line2"},"address_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address City"},"address_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address State"},"address_postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Postal Code"},"address_country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Country"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"default_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Currency"}},"type":"object","title":"ConnectProfile"},"ConnectorRecord":{"properties":{"id":{"type":"integer","title":"Id"},"number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Number"},"evse_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Evse Number"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"tariff_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tariff Id"}},"type":"object","required":["id","number","evse_number","status","tariff_id"],"title":"ConnectorRecord"},"ContextRecord":{"properties":{"workspace":{"anyOf":[{"$ref":"#/components/schemas/WorkspaceRecord"},{"type":"null"}]},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes"},"is_owner":{"type":"boolean","title":"Is Owner"}},"type":"object","required":["workspace","scopes","is_owner"],"title":"ContextRecord"},"DNSRecord":{"properties":{"type":{"type":"string","enum":["A","CNAME","TXT"],"title":"Type"},"name":{"type":"string","title":"Name"},"value":{"type":"string","title":"Value"},"ttl":{"type":"integer","title":"Ttl"},"proxied":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Proxied"}},"type":"object","required":["type","name","value","ttl"],"title":"DNSRecord"},"DeliveryList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DeliveryRecord"},"type":"array","title":"Data"},"next_cursor":{"type":"integer","title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"DeliveryList"},"DeliveryRecord":{"properties":{"id":{"type":"string","title":"Id"},"webhook_id":{"type":"string","title":"Webhook Id"},"event_id":{"type":"string","title":"Event Id"},"event_sequence":{"type":"integer","title":"Event Sequence"},"event_type":{"type":"string","title":"Event Type"},"status":{"type":"string","enum":["pending","delivered","failed"],"title":"Status"},"attempts":{"type":"integer","title":"Attempts"},"next_attempt_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Attempt At"},"last_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Status"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","webhook_id","event_id","event_sequence","event_type","status","attempts","next_attempt_at","last_status","last_error","created_at","updated_at"],"title":"DeliveryRecord"},"DisplayDelivery":{"properties":{"state":{"type":"string","enum":["pending","applied","failed","unsupported"],"title":"State","description":"applied: the charging core dispatched the latest push, which does not confirm what the screen shows (the generic OCPP 2.x adapters cannot tell whether a charger has a screen). unsupported: no adapter drives this charger's screen; use a printed QR."},"shown":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Shown","description":"Whether the last applied push sent the QR (false after a clear); null before the first push."},"revision":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revision","description":"Desired revision the last successful push carried."},"applied_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Applied At"},"last_attempt_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Attempt At"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error","description":"Error code of the last failed push, for example dispatch_unconfirmed or template_render_failed."}},"type":"object","required":["state","shown","revision","applied_at","last_attempt_at","last_error"],"title":"DisplayDelivery"},"DisplayInput":{"properties":{"qr":{"type":"string","maxLength":500,"minLength":1,"title":"Qr","description":"https URL the screen encodes as a QR, usually your checkout page for this EVSE. No customer data or secrets.","examples":["https://payment.ivoracharge.com/checkout/station-01-1"]},"show_price":{"type":"boolean","title":"Show Price","description":"Also show the price where the adapter supports it: the tariff_id tariff when set, else the EVSE's connector tariff.","default":true},"tariff_id":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Tariff Id","description":"A tariff in this tenant whose price the screen shows, usually the one your application bills with. Omit to use the EVSE's connector tariff.","examples":[42]},"visibility":{"type":"string","enum":["idle","always"],"title":"Visibility","description":"idle shows the QR only while the connector is payable, on adapters that can clear; always keeps it up.","default":"idle"}},"additionalProperties":false,"type":"object","required":["qr"],"title":"DisplayInput"},"DisplayList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DisplayRecord"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"DisplayList"},"DisplayRecord":{"properties":{"id":{"type":"string","title":"Id","description":"<station_id>-<evse_number>"},"tenant_id":{"type":"integer","title":"Tenant Id"},"station_id":{"type":"integer","title":"Station Id"},"evse_number":{"type":"integer","title":"Evse Number"},"qr":{"type":"string","title":"Qr"},"show_price":{"type":"boolean","title":"Show Price"},"visibility":{"type":"string","enum":["idle","always"],"title":"Visibility"},"tariff_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tariff Id","description":"Tariff the screen's price comes from; null uses the EVSE's connector tariff."},"revision":{"type":"integer","title":"Revision","description":"Increments whenever qr, show_price, visibility or tariff_id changes."},"adapter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Adapter","description":"Display adapter template that last resolved for this charger, for example builtin-rcd."},"clear":{"type":"boolean","title":"Clear","description":"The adapter can take the QR off the screen."},"deleted":{"type":"boolean","title":"Deleted"},"delivery":{"$ref":"#/components/schemas/DisplayDelivery"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","tenant_id","station_id","evse_number","qr","show_price","visibility","tariff_id","revision","adapter","clear","deleted","delivery","updated_at"],"title":"DisplayRecord"},"DomainInput":{"properties":{"hostname":{"type":"string","maxLength":221,"minLength":3,"title":"Hostname","examples":["ocpp.example.com"]}},"additionalProperties":false,"type":"object","required":["hostname"],"title":"DomainInput"},"DomainList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/DomainRecord"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"DomainList"},"DomainRecord":{"properties":{"id":{"type":"string","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"hostname":{"type":"string","title":"Hostname"},"status":{"type":"string","enum":["pending_dns","dns_verified","active","disabled"],"title":"Status"},"created_at":{"type":"string","title":"Created At"},"checked_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checked At"},"verified_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verified At"},"activated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activated At"},"certificate_expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Certificate Expires At"},"activation_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activation Error"},"dns_records":{"items":{"$ref":"#/components/schemas/DNSRecord"},"type":"array","title":"Dns Records"},"checks":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Checks"},"connection_url_template":{"type":"string","title":"Connection Url Template"},"ready":{"type":"boolean","title":"Ready"}},"type":"object","required":["id","tenant_id","hostname","status","created_at","checked_at","verified_at","activated_at","certificate_expires_at","activation_error","dns_records","checks","connection_url_template","ready"],"title":"DomainRecord"},"ErrorDetail":{"properties":{"code":{"type":"string","title":"Code","description":"Stable machine-readable condition, for example station_offline or idempotency_key_reused. Generic codes (not_found, conflict, invalid_request) remain for conditions without a specific code."},"message":{"type":"string","title":"Message"},"details":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Details","description":"Optional structured context such as operation_id or resource_id."}},"type":"object","required":["code","message"],"title":"ErrorDetail"},"ErrorResponse":{"properties":{"error":{"$ref":"#/components/schemas/ErrorDetail"},"request_id":{"type":"string","title":"Request Id"}},"type":"object","required":["error","request_id"],"title":"ErrorResponse"},"ExternalSessionInput":{"properties":{"station_id":{"type":"integer","exclusiveMinimum":0,"title":"Station Id"},"connector_id":{"type":"integer","exclusiveMinimum":0,"title":"Connector Id"},"tariff_id":{"type":"integer","exclusiveMinimum":0,"title":"Tariff Id","description":"Tenant-owned tariff, snapshotted before charging"},"source":{"type":"string","enum":["csms","simulated"],"title":"Source","default":"csms"},"application_reference":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$","title":"Application Reference","description":"Unique booking/session reference within your tenant. No customer data or secrets."},"processor":{"type":"string","pattern":"^[a-z][a-z0-9-]{0,31}$","title":"Processor","description":"Descriptive payment integration name. No adapter is called."},"merchant_reference":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$","title":"Merchant Reference","description":"Your non-secret processor account reference."},"payment_reference":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$","title":"Payment Reference","description":"Stable external payment reference, unique per tenant, processor and merchant."}},"additionalProperties":false,"type":"object","required":["station_id","connector_id","tariff_id","application_reference","processor","merchant_reference","payment_reference"],"title":"ExternalSessionInput"},"ExternalSessionList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ExternalSessionRecord"},"type":"array","title":"Data"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"ExternalSessionList"},"ExternalSessionRecord":{"properties":{"id":{"type":"string","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"application_reference":{"type":"string","title":"Application Reference"},"processor":{"type":"string","title":"Processor"},"merchant_reference":{"type":"string","title":"Merchant Reference"},"payment_reference":{"type":"string","title":"Payment Reference"},"created_by":{"type":"string","title":"Created By"},"created_at":{"type":"string","title":"Created At"},"settlement_owner":{"type":"string","const":"external","title":"Settlement Owner","default":"external"},"status":{"type":"string","enum":["prepared","starting","charging","stopping","awaiting_bill","completed","canceled","reconciliation_required"],"title":"Status"},"bill":{"$ref":"#/components/schemas/BillRecord"},"usage":{"anyOf":[{"$ref":"#/components/schemas/UsageRecord"},{"type":"null"}],"description":"Live matched usage while charging; a final snapshot once completed. Null before a transaction is observed and on canceled sessions."},"start_operation":{"anyOf":[{"$ref":"#/components/schemas/OperationRecord"},{"type":"null"}]},"stop_operation":{"anyOf":[{"$ref":"#/components/schemas/OperationRecord"},{"type":"null"}]},"settlement":{"$ref":"#/components/schemas/SettlementSummary"}},"type":"object","required":["id","tenant_id","application_reference","processor","merchant_reference","payment_reference","created_by","created_at","status","bill","usage","start_operation","stop_operation","settlement"],"title":"ExternalSessionRecord"},"ExternalStartInput":{"properties":{"funding_confirmed":{"type":"boolean","const":true,"title":"Funding Confirmed","description":"Your backend attests it has authorized funding. Ivora cannot independently verify this assertion or enforce the processor's hold."}},"additionalProperties":false,"type":"object","required":["funding_confirmed"],"title":"ExternalStartInput"},"FaultList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/FaultRecord"},"type":"array","title":"Data"},"next_cursor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Next Cursor","description":"Pass as before for the next, older page; null on the last page."}},"type":"object","required":["data","next_cursor"],"title":"FaultList"},"FaultRecord":{"properties":{"id":{"type":"string","title":"Id","description":"fault_id in station.fault_opened and station.fault_cleared events."},"station_id":{"type":"integer","title":"Station Id"},"connector_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Connector Id","description":"Connector resource ID; null when the charger reported the fault for the whole station."},"evse_number":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Evse Number"},"open":{"type":"boolean","title":"Open"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code","description":"OCPP 1.6 errorCode other than NoError; null for an OCPP 2.x Faulted status without one."},"info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Info"},"vendor_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Id"},"vendor_error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Error Code"},"ocpp_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ocpp Status","description":"The status the charger reported with the fault, as sent."},"opened_at":{"type":"string","title":"Opened At","description":"The charger's timestamp of the notification that opened the fault, else when Ivora observed it."},"cleared_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cleared At"}},"type":"object","required":["id","station_id","connector_id","evse_number","open","error_code","info","vendor_id","vendor_error_code","ocpp_status","opened_at","cleared_at"],"title":"FaultRecord"},"FinalizeInput":{"properties":{"transaction_id":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Transaction Id"},"energy_wh":{"anyOf":[{"type":"integer","maximum":50000,"minimum":0},{"type":"null"}],"title":"Energy Wh","description":"Simulation only. Physical usage is read from CSMS, never accepted from the caller."}},"additionalProperties":false,"type":"object","title":"FinalizeInput"},"KeyInput":{"properties":{"label":{"type":"string","maxLength":80,"minLength":2,"title":"Label"},"scopes":{"items":{"type":"string"},"type":"array","maxItems":16,"minItems":1,"title":"Scopes"},"tenant_id":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"title":"Tenant Id","description":"CSMS keys default to the tenant of your access grant. An explicit tenant is checked against your current access. The key stays bound to that tenant."}},"additionalProperties":false,"type":"object","required":["label","scopes"],"title":"KeyInput"},"LocationInput":{"properties":{"name":{"type":"string","maxLength":80,"minLength":2,"title":"Name"},"address":{"type":"string","maxLength":120,"title":"Address","default":""},"city":{"type":"string","maxLength":120,"title":"City","default":""},"state":{"type":"string","maxLength":120,"title":"State","default":""},"country":{"type":"string","pattern":"^[A-Z]{3}$","title":"Country","default":"USA"},"postal_code":{"type":"string","maxLength":20,"title":"Postal Code","default":""},"latitude":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Latitude","description":"Optional; supply latitude and longitude together."},"longitude":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Longitude"},"time_zone":{"type":"string","maxLength":80,"minLength":1,"title":"Time Zone","default":"America/New_York"},"external_reference":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$"},{"type":"null"}],"title":"External Reference","description":"Your stable identifier for this resource (for example a property or listing ID). Unique per tenant and resource type. Filter lists with ?external_reference=. No customer data or secrets."}},"additionalProperties":false,"type":"object","required":["name"],"title":"LocationInput"},"LocationList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/LocationRecord"},"type":"array","title":"Data"},"next_cursor":{"type":"integer","title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"LocationList"},"LocationRecord":{"properties":{"id":{"type":"integer","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"time_zone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time Zone"},"external_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Reference"}},"type":"object","required":["id","tenant_id","name","address","city","state","country","postal_code","latitude","longitude","time_zone"],"title":"LocationRecord"},"LocationUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":80,"minLength":2},{"type":"null"}],"title":"Name"},"address":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Address"},"city":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"State"},"country":{"anyOf":[{"type":"string","pattern":"^[A-Z]{3}$"},{"type":"null"}],"title":"Country"},"postal_code":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Postal Code"},"latitude":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Longitude"},"time_zone":{"anyOf":[{"type":"string","maxLength":80,"minLength":1},{"type":"null"}],"title":"Time Zone"}},"additionalProperties":false,"type":"object","title":"LocationUpdate"},"MeterOptions":{"properties":{"sample_interval_seconds":{"type":"integer","maximum":3600,"minimum":10,"title":"Sample Interval Seconds","description":"Minimum seconds between meter.sampled deliveries of one transaction to this endpoint. A transaction's first and last samples are always delivered.","default":60}},"additionalProperties":false,"type":"object","title":"MeterOptions"},"Onboarding":{"properties":{"portal":{"type":"string","enum":["analytics","host"],"title":"Portal","description":"Where Stripe returns the host: analytics is the Platform's /host page; host is a retired alias for the same page, accepted only where the environment still allows it.","default":"analytics"}},"additionalProperties":false,"type":"object","title":"Onboarding"},"OnboardingLinkRecord":{"properties":{"url":{"type":"string","title":"Url","description":"Single-use Stripe onboarding link; open it now."},"stripe_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Account Id"}},"type":"object","required":["url"],"title":"OnboardingLinkRecord"},"OperationRecord":{"properties":{"id":{"type":"string","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"status":{"type":"string","enum":["dispatching","succeeded","rejected","unknown"],"title":"Status"},"result":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Result"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","tenant_id","status","result","created_at","updated_at"],"title":"OperationRecord"},"PasswordInput":{"properties":{"password":{"type":"string","pattern":"^[a-zA-Z0-9*\\-_=:+|@.]{16,40}$","title":"Password","writeOnly":true}},"additionalProperties":false,"type":"object","required":["password"],"title":"PasswordInput"},"PaymentAccountRecord":{"properties":{"stripe_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Account Id"},"charges_enabled":{"type":"boolean","title":"Charges Enabled","default":false},"details_submitted":{"type":"boolean","title":"Details Submitted","default":false},"disabled_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disabled Reason"},"requirements_due":{"items":{"type":"string"},"type":"array","title":"Requirements Due","default":[]},"profile":{"anyOf":[{"$ref":"#/components/schemas/ConnectProfile"},{"type":"null"}]},"source":{"anyOf":[{"type":"string","enum":["onboarding","legacy_import","staff"]},{"type":"null"}],"title":"Source","description":"How the account was pinned."},"status":{"type":"string","enum":["none","pending_review","active","disconnected"],"title":"Status","description":"active: new payments charge this account. pending_review: onboarded, awaiting Ivora approval. none or disconnected: no payment account."},"livemode":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Livemode","description":"Whether the account was read with a live Stripe key."}},"type":"object","required":["status"],"title":"PaymentAccountRecord"},"PaymentDetail":{"properties":{"id":{"type":"string","title":"Id"},"bill_id":{"type":"string","title":"Bill Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"service":{"type":"string","title":"Service"},"status":{"type":"string","enum":["preparing","pending","authorized","captured","canceled","refund_pending","refund_failed","refunded"],"title":"Status"},"hold_minor":{"type":"integer","title":"Hold Minor"},"captured_minor":{"type":"integer","title":"Captured Minor"},"refunded_minor":{"type":"integer","title":"Refunded Minor"},"currency":{"type":"string","const":"USD","title":"Currency","default":"USD"},"payment_mode":{"type":"string","enum":["test","live"],"title":"Payment Mode","description":"live only for a Stripe payment taken in live mode on a connected account, as the provider recorded it at authorization; test otherwise."},"authorized_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Authorized At","description":"When Stripe authorized the hold (the Charge's creation time); null before authorization and for the simulator."},"next_action":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Next Action"},"processor_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processor Reference","description":"The processor's payment reference (a Stripe PaymentIntent ID), for reconciliation in its dashboard."},"customer_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Email","description":"The email the driver entered at hosted checkout, for receipts. Personal data: store and show it only to this tenant."}},"type":"object","required":["id","bill_id","tenant_id","service","status","hold_minor","captured_minor","refunded_minor","payment_mode","next_action"],"title":"PaymentDetail","description":"The tenant-scoped single payment read: adds the processor reference and the checkout email."},"PaymentInput":{"properties":{"bill_id":{"type":"string","pattern":"^bill_[0-9a-f]{32}$","title":"Bill Id"},"return_surface":{"type":"string","enum":["developer","driver"],"title":"Return Surface","description":"Where hosted checkout returns: the developer sandbox page, or the driver charging page for this bill's station and connector (server-selected URLs).","default":"developer"},"return_reference":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$"},{"type":"null"}],"title":"Return Reference","description":"Driver surface only: your session identifier appended to the server-selected return path (/charging/<evse>/<reference>) so the driver page can resume this session. Not a URL."}},"additionalProperties":false,"type":"object","required":["bill_id"],"title":"PaymentInput"},"PaymentRecord":{"properties":{"id":{"type":"string","title":"Id"},"bill_id":{"type":"string","title":"Bill Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"service":{"type":"string","title":"Service"},"status":{"type":"string","enum":["preparing","pending","authorized","captured","canceled","refund_pending","refund_failed","refunded"],"title":"Status"},"hold_minor":{"type":"integer","title":"Hold Minor"},"captured_minor":{"type":"integer","title":"Captured Minor"},"refunded_minor":{"type":"integer","title":"Refunded Minor"},"currency":{"type":"string","const":"USD","title":"Currency","default":"USD"},"payment_mode":{"type":"string","enum":["test","live"],"title":"Payment Mode","description":"live only for a Stripe payment taken in live mode on a connected account, as the provider recorded it at authorization; test otherwise."},"authorized_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Authorized At","description":"When Stripe authorized the hold (the Charge's creation time); null before authorization and for the simulator."},"next_action":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Next Action"}},"type":"object","required":["id","bill_id","tenant_id","service","status","hold_minor","captured_minor","refunded_minor","payment_mode","next_action"],"title":"PaymentRecord"},"RunningCostInput":{"properties":{"enabled":{"type":"boolean","title":"Enabled","description":"Send the running and final cost of this station's bills to the charger screen (California CTEP). On by default; an explicit choice always wins over the default."},"interval_seconds":{"type":"integer","maximum":900,"minimum":15,"title":"Interval Seconds","description":"Least time between two running cost messages of one session; a message goes out only when energy or cost changed.","default":60}},"additionalProperties":false,"type":"object","required":["enabled"],"title":"RunningCostInput"},"RunningCostRecord":{"properties":{"tenant_id":{"type":"integer","title":"Tenant Id"},"station_id":{"type":"integer","title":"Station Id"},"enabled":{"type":"boolean","title":"Enabled","description":"Whether this station's bills get running cost messages: the explicit choice, else this environment's default (on; capabilities running_cost.default)."},"interval_seconds":{"type":"integer","title":"Interval Seconds"},"source":{"type":"string","enum":["default","manual"],"title":"Source","description":"default: no explicit choice, enabled follows the environment's default. manual: set by PUT (updated_by, updated_at) and kept until changed."},"updated_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated By","description":"Who wrote the explicit choice (user: or key:); null for the default."},"support":{"type":"string","enum":["ocpp16_costmsg","ocpp2_cost_updated","ocpp2_deferred","charger_rejected","not_booted","protocol_unsupported"],"title":"Support","description":"ocpp16_costmsg: OCA California Pricing DataTransfer (org.openchargealliance.costmsg RunningCost and FinalCost). ocpp2_cost_updated: CostUpdated during the session. ocpp2_deferred: OCPP 2.x cost messages are switched off in this environment while the charging core sends its own. charger_rejected: the OCPP 1.6 charger answered RunningCost with UnknownVendorId, UnknownMessageId or Rejected (see rejection); nothing is sent until it reboots or the setting is written. not_booted: the charger has not reported its protocol yet."},"rejection":{"anyOf":[{"$ref":"#/components/schemas/RunningCostRejection"},{"type":"null"}],"description":"The charger's refusal while support is charger_rejected, else null."},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At","description":"When the explicit choice was last changed; null for the default."},"sessions":{"anyOf":[{"items":{"$ref":"#/components/schemas/RunningCostSession"},"type":"array"},{"type":"null"}],"title":"Sessions","description":"The 20 most recent priced sessions on this station, newest first; null without billing:read."}},"type":"object","required":["tenant_id","station_id","enabled","interval_seconds","source","updated_by","support","rejection","updated_at","sessions"],"title":"RunningCostRecord"},"RunningCostRejection":{"properties":{"status":{"type":"string","enum":["UnknownVendorId","UnknownMessageId","Rejected"],"title":"Status","description":"The charger's DataTransfer.conf status."},"at":{"type":"string","title":"At","description":"When the charging core received the refusal."}},"type":"object","required":["status","at"],"title":"RunningCostRejection"},"RunningCostSession":{"properties":{"bill_id":{"type":"string","title":"Bill Id"},"transaction_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transaction Id","description":"Core transaction the bill matched."},"protocol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Protocol"},"state":{"type":"string","enum":["running","final_pending","final_sent","final_rejected","final_by_core","deferred","expired","failed"],"title":"State","description":"running: running cost messages are being sent. final_pending: the session ended and its final cost is being sent (OCPP 1.6). final_sent: the charging core accepted the final cost message. final_rejected: the charger refused the final cost (last_error final_cost_rejected; some chargers refuse it once the transaction has stopped); the station and its later sessions are unaffected. final_by_core: OCPP 2.x carries the final cost in the core's TransactionEvent response. deferred: OCPP 2.x CostUpdated is switched off in this environment. expired: the final cost could not be sent within an hour of the end. failed: the bill could not be priced or matched; last_error has the code."},"currency":{"type":"string","title":"Currency"},"cost_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cost Minor","description":"Latest running cost in minor units: energy × the bill's rate, as bill finalization rounds it."},"energy_wh":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Energy Wh","description":"Session energy in Wh at cost_minor."},"sent_cost_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sent Cost Minor","description":"Running cost in minor units the core last accepted."},"sent_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sent At"},"sends":{"type":"integer","title":"Sends","description":"Running cost messages the core accepted for this session."},"final_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Final Minor","description":"Final cost in minor units: the final bill's total, or the same calculation from the ended transaction."},"final_sent_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Final Sent At"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error","description":"Error code of the last failed or withheld send, for example dispatch_unconfirmed, station_offline, charger_rejected or final_cost_rejected."},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["bill_id","transaction_id","protocol","state","currency","cost_minor","energy_wh","sent_cost_minor","sent_at","sends","final_minor","final_sent_at","last_error","updated_at"],"title":"RunningCostSession"},"SettlementReportInput":{"properties":{"kind":{"type":"string","enum":["authorization","capture","refund","release"],"title":"Kind"},"operation_reference":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$","title":"Operation Reference","description":"Stable processor operation ID. Reuse for outcome updates; use a new ID only for a distinct financial operation."},"outcome":{"type":"string","enum":["pending","unknown","succeeded","failed"],"title":"Outcome"},"amount_minor":{"type":"integer","maximum":10000000000,"minimum":0,"title":"Amount Minor","description":"Integer USD cents. Release uses zero. This reports a fact; it never moves money."},"currency":{"type":"string","const":"USD","title":"Currency","default":"USD"}},"additionalProperties":false,"type":"object","required":["kind","operation_reference","outcome","amount_minor"],"title":"SettlementReportInput"},"SettlementReportList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SettlementReportRecord"},"type":"array","title":"Data"},"next_cursor":{"type":"integer","title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"SettlementReportList"},"SettlementReportRecord":{"properties":{"sequence":{"type":"integer","title":"Sequence"},"id":{"type":"string","title":"Id"},"session_id":{"type":"string","title":"Session Id"},"kind":{"type":"string","enum":["authorization","capture","refund","release"],"title":"Kind"},"operation_reference":{"type":"string","title":"Operation Reference"},"outcome":{"type":"string","enum":["pending","unknown","succeeded","failed"],"title":"Outcome"},"amount_minor":{"type":"integer","title":"Amount Minor"},"currency":{"type":"string","const":"USD","title":"Currency"},"reported_by":{"type":"string","title":"Reported By"},"created_at":{"type":"string","title":"Created At"},"verification":{"type":"string","const":"application_reported","title":"Verification","default":"application_reported"}},"type":"object","required":["sequence","id","session_id","kind","operation_reference","outcome","amount_minor","currency","reported_by","created_at"],"title":"SettlementReportRecord"},"SettlementSummary":{"properties":{"verification":{"type":"string","const":"application_reported","title":"Verification","default":"application_reported"},"captured_minor":{"type":"integer","title":"Captured Minor"},"refunded_minor":{"type":"integer","title":"Refunded Minor"},"net_minor":{"type":"integer","title":"Net Minor"},"uncollected_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Uncollected Minor"},"status":{"type":"string","enum":["unreported","pending","unknown","failed","reported_unpaid","reported_partial","reported_paid","reported_refunded","reported_released"],"title":"Status"}},"type":"object","required":["captured_minor","refunded_minor","net_minor","uncollected_minor","status"],"title":"SettlementSummary"},"SetupLink":{"properties":{"available":{"type":"boolean","title":"Available"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"message":{"type":"string","title":"Message"}},"type":"object","required":["available","message"],"title":"SetupLink"},"StationDeleted":{"properties":{"id":{"type":"integer","title":"Id"},"deleted":{"type":"boolean","const":true,"title":"Deleted","default":true}},"type":"object","required":["id"],"title":"StationDeleted"},"StationDisplay":{"properties":{"adapter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Adapter","description":"Display adapter template that drives this charger's screen, or null when none applies."},"reason":{"type":"string","enum":["assigned","matched","not_booted","no_adapter","assigned_unpublished","protocol_unsupported"],"title":"Reason"},"qr":{"type":"boolean","title":"Qr","description":"The adapter sends the payment QR to the charger's screen. The generic OCPP 2.x adapters cannot tell whether the charger has a screen, so keep a printed QR."},"price":{"type":"boolean","title":"Price","description":"The adapter also sends a price: the display's tariff_id, else the connector tariff."},"clear":{"type":"boolean","title":"Clear","description":"The adapter can take a QR off the screen. When false the QR can stay, even after a DELETE: until the charger reboots on RCD/Renova, until it is overwritten on Sinexcel (its configuration keys persist)."},"evses":{"items":{"$ref":"#/components/schemas/StationDisplayEvse"},"type":"array","title":"Evses","description":"Configured displays and their delivery state; manage them under /evses/{evse_number}/display."}},"type":"object","required":["adapter","reason","qr","price","clear","evses"],"title":"StationDisplay"},"StationDisplayEvse":{"properties":{"evse_number":{"type":"integer","title":"Evse Number"},"state":{"type":"string","enum":["pending","applied","failed","unsupported"],"title":"State"},"shown":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Shown"}},"type":"object","required":["evse_number","state","shown"],"title":"StationDisplayEvse"},"StationInput":{"properties":{"name":{"type":"string","pattern":"^[a-zA-Z0-9][a-zA-Z0-9_-]{2,59}$","title":"Name","description":"Globally unique OCPP connection name; the charger connects at <connection_url>."},"location_id":{"type":"integer","exclusiveMinimum":0,"title":"Location Id"},"connectors":{"type":"integer","maximum":8,"minimum":1,"title":"Connectors","default":1},"external_reference":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$"},{"type":"null"}],"title":"External Reference","description":"Your stable identifier for this resource (for example a property or listing ID). Unique per tenant and resource type. Filter lists with ?external_reference=. No customer data or secrets."}},"additionalProperties":false,"type":"object","required":["name","location_id"],"title":"StationInput"},"StationList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/StationRecord"},"type":"array","title":"Data"},"next_cursor":{"type":"integer","title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"StationList"},"StationRecord":{"properties":{"id":{"type":"integer","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"name":{"type":"string","title":"Name"},"online":{"type":"boolean","title":"Online"},"protocol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Protocol"},"location_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Location Id"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"serial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial"},"last_seen":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen","description":"Timestamp of the last OCPP message from this charger, if any."},"connectors":{"items":{"$ref":"#/components/schemas/ConnectorRecord"},"type":"array","title":"Connectors"},"connection_url":{"type":"string","title":"Connection Url","description":"Default OCPP WebSocket URL for this station name. Custom OCPP domains publish their own template."},"external_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Reference"},"display":{"$ref":"#/components/schemas/StationDisplay","description":"Whether Ivora can drive this charger's screen, and the configured displays."},"open_faults":{"items":{"$ref":"#/components/schemas/FaultRecord"},"type":"array","title":"Open Faults","description":"Faults still open, from the charger's status notifications; history at /faults."}},"type":"object","required":["id","tenant_id","name","online","protocol","location_id","vendor","model","connectors","connection_url","display"],"title":"StationRecord"},"StationUpdate":{"properties":{"location_id":{"type":"integer","exclusiveMinimum":0,"title":"Location Id"}},"additionalProperties":false,"type":"object","required":["location_id"],"title":"StationUpdate"},"TariffInput":{"properties":{"currency":{"type":"string","pattern":"^[A-Z]{3}$","title":"Currency"},"rate_minor_per_kwh":{"type":"integer","maximum":100000,"minimum":0,"title":"Rate Minor Per Kwh","description":"Integer minor units per kWh (USD cents)."},"authorization_minor":{"type":"integer","maximum":100000,"minimum":0,"title":"Authorization Minor","description":"Integer minor units held before charging."},"external_reference":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,127}$"},{"type":"null"}],"title":"External Reference","description":"Your stable identifier for this resource (for example a property or listing ID). Unique per tenant and resource type. Filter lists with ?external_reference=. No customer data or secrets."}},"additionalProperties":false,"type":"object","required":["currency","rate_minor_per_kwh","authorization_minor"],"title":"TariffInput"},"TariffList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TariffRecord"},"type":"array","title":"Data"},"next_cursor":{"type":"integer","title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"TariffList"},"TariffRecord":{"properties":{"id":{"type":"integer","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"currency":{"type":"string","title":"Currency"},"rate_minor_per_kwh":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Rate Minor Per Kwh","description":"Integer minor units per kWh. Tariffs created elsewhere with sub-cent rates return a decimal number."},"authorization_minor":{"anyOf":[{"type":"integer"},{"type":"number"}],"title":"Authorization Minor"},"external_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Reference"}},"type":"object","required":["id","tenant_id","currency","rate_minor_per_kwh","authorization_minor"],"title":"TariffRecord"},"TenantAssignment":{"properties":{"tenant_id":{"type":"integer","exclusiveMinimum":0,"title":"Tenant Id","description":"Your stable default CSMS tenant ID; use it in /v1/tenants/{tenant_id} routes."},"roles":{"items":{"type":"string"},"type":"array","title":"Roles","description":"Current permissions. Existing viewers are not promoted during onboarding."}},"type":"object","required":["tenant_id","roles"],"title":"TenantAssignment"},"TenantEventList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/TenantEventRecord"},"type":"array","title":"Data"},"next_cursor":{"type":"integer","title":"Next Cursor"}},"type":"object","required":["data","next_cursor"],"title":"TenantEventList"},"TenantEventRecord":{"properties":{"id":{"type":"string","title":"Id"},"sequence":{"type":"integer","title":"Sequence"},"tenant_id":{"type":"integer","title":"Tenant Id"},"type":{"type":"string","enum":["operation.completed","charging_session.status_changed","bill.finalized","webhook.test","display.delivery_changed","station.connected","station.disconnected","station.booted","connector.status_changed","station.fault_opened","station.fault_cleared","meter.sampled"],"title":"Type"},"resource_id":{"type":"string","title":"Resource Id"},"data":{"type":"object","title":"Data"},"created_at":{"type":"string","title":"Created At"},"station_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Station Id","description":"Charger events only: the station resource ID."},"station_sequence":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Station Sequence","description":"Charger events only: increases by one with each event of this station; order a station's events by it."},"occurred_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occurred At","description":"Charger events only: when the charger reported it (its own clock), when known."}},"type":"object","required":["id","sequence","tenant_id","type","resource_id","data","created_at"],"title":"TenantEventRecord"},"TestResult":{"properties":{"event_id":{"type":"string","title":"Event Id"},"delivery_queued":{"type":"boolean","title":"Delivery Queued"}},"type":"object","required":["event_id","delivery_queued"],"title":"TestResult"},"UsageRecord":{"properties":{"transaction_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transaction Id","description":"Physical transaction resource ID; null for simulated bills."},"active":{"type":"boolean","title":"Active"},"energy_kwh":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Energy Kwh","description":"Decimal kWh string for display."},"energy_wh":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Energy Wh","description":"Integer Wh for arithmetic."},"estimated_minor":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Minor","description":"Integer minor units. On final bills this equals total_minor."},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At"},"ended_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ended At"},"power_w":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Power W","description":"Latest reported charging power in watts; 0 once the transaction ended; null when the charger reports none."},"soc_percent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Soc Percent","description":"Latest reported vehicle state of charge, when the charger reports it."},"metered_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metered At","description":"Timestamp of the meter sample behind power_w/soc_percent."}},"type":"object","required":["transaction_id","active","energy_kwh","energy_wh","estimated_minor","started_at","ended_at"],"title":"UsageRecord"},"WebhookInput":{"properties":{"url":{"type":"string","maxLength":512,"minLength":12,"title":"Url","examples":["https://app.example.com/ivora/webhooks"]},"events":{"items":{"type":"string","enum":["operation.completed","charging_session.status_changed","bill.finalized","webhook.test","display.delivery_changed","station.connected","station.disconnected","station.booted","connector.status_changed","station.fault_opened","station.fault_cleared","meter.sampled"]},"type":"array","maxItems":12,"minItems":1,"title":"Events","description":"Event types to deliver. Each requires the read scope of the data it carries."},"description":{"type":"string","maxLength":120,"title":"Description","default":""},"stations":{"anyOf":[{"items":{"type":"integer"},"type":"array","maxItems":500,"minItems":1},{"type":"null"}],"title":"Stations","description":"Deliver station, connector, fault and meter events of these station resource IDs only. Omit for every station. Other event types are unaffected."},"meter":{"anyOf":[{"$ref":"#/components/schemas/MeterOptions"},{"type":"null"}],"description":"meter.sampled options; the default interval is 60 seconds."}},"additionalProperties":false,"type":"object","required":["url","events"],"title":"WebhookInput"},"WebhookList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WebhookRecord"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"WebhookList"},"WebhookRecord":{"properties":{"id":{"type":"string","title":"Id"},"tenant_id":{"type":"integer","title":"Tenant Id"},"url":{"type":"string","title":"Url"},"events":{"items":{"type":"string","enum":["operation.completed","charging_session.status_changed","bill.finalized","webhook.test","display.delivery_changed","station.connected","station.disconnected","station.booted","connector.status_changed","station.fault_opened","station.fault_cleared","meter.sampled"]},"type":"array","title":"Events"},"description":{"type":"string","title":"Description"},"status":{"type":"string","enum":["active","disabled"],"title":"Status"},"created_at":{"type":"string","title":"Created At"},"disabled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disabled At"},"stations":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Stations","description":"Station filter for station, connector, fault and meter events; null delivers every station."},"meter":{"$ref":"#/components/schemas/MeterOptions"},"secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret","description":"Returned once at creation. Verify Ivora-Signature with HMAC-SHA256 over '<timestamp>.<raw body>'."}},"type":"object","required":["id","tenant_id","url","events","description","status","created_at","disabled_at"],"title":"WebhookRecord"},"WorkspaceInput":{"properties":{"name":{"type":"string","maxLength":80,"minLength":2,"title":"Name"}},"additionalProperties":false,"type":"object","required":["name"],"title":"WorkspaceInput"},"WorkspaceRecord":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"color":{"type":"string","title":"Color"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","name","color","created_at"],"title":"WorkspaceRecord"}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"Paste a tenant-scoped iv_live_ API key or Supabase access token without the Bearer prefix. API keys cannot manage other keys.","scheme":"bearer"}}},"tags":[{"name":"Getting started","description":"Public service discovery, health, configuration and supported integrations."},{"name":"Access and API keys","description":"Retrieve the charging tenant of your access grant, discover current access and issue or revoke scoped keys. CSMS keys default to your assigned tenant. Onboarding, workspaces and key management require a signed-in user with an access grant from Ivora; keys cannot onboard users or issue other keys."},{"name":"Payment account","description":"The tenant's Stripe Connect account at /payment/stripe/v1/tenants/{tenant_id}/account: status (billing:read), onboarding and disconnect (a signed-in tenant-admin; API keys are refused). The payment provider's pin is the only charge destination: Stripe payments of physical bills are direct charges on it. Tenants without an active pin get payment_account_required."},{"name":"Locations","description":"Tenant-owned charging locations. Creation is synchronous and returns the location with its ID. Requires stations:read for reads or stations:write for creation. Optional external_reference makes a location findable by your own identifier."},{"name":"Stations","description":"Register stations (synchronous, returns the station), read connector state, assign locations and set connection credentials. Requires stations:read or stations:write. Resource connector IDs differ from OCPP connector numbers. Credentials and moves return operations because they can touch hardware. Faults observed from the charger's status notifications are listed per station."},{"name":"Charger displays","description":"Declare the payment QR a charger screen shows per EVSE. Ivora stores the desired state and keeps pushing it after reboots, revision and tariff changes; writes never wait for the charger. delivery.state applied means the charging core accepted the push, not that the panel changed. Price comes from the tariff_id you set, else the connector tariff. Requires stations:read or stations:write. Adapters with clear: false keep the last QR: RCD/Renova until the charger reboots, Sinexcel until it is overwritten. running-cost: California CTEP running and final cost messages, on by default for every station; a station's explicit on or off always wins: OCPP 1.6 by the Open Charge Alliance California Pricing DataTransfer, OCPP 2.x by CostUpdated where enabled; session amounts need billing:read."},{"name":"OCPP domains","description":"Tenant custom charger hostnames, DNS records, provider-approved automatic setup and TLS readiness. Requires stations:read or stations:write. Cloudflare Domain Connect needs an onboarded signed template. DNS verification alone does not activate a domain."},{"name":"Charging and operations","description":"Dispatch charger commands, start an authorized bill, observe transactions and inspect operations. Commands require stations:control; bill start also requires billing:write. Transaction reads require billing:read. A successful dispatch is not confirmation that charging began."},{"name":"Tariffs and bills","description":"Create immutable tariff versions (synchronous, returns the tariff), snapshot one before charging and calculate an immutable bill from trusted completed usage. Requires billing:read or billing:write. Energy is reported as integer Wh alongside a decimal kWh string; money is integer minor units."},{"name":"Payments","description":"Discover configured adapters, then authorize, inspect, capture, release or refund at /payment/{service}/v1/tenants/{tenant_id}. Services: stripe (live mode, where enabled) and simulator. Requires billing:read or billing:write, and billing:refund for refunds; one payment per bill. payment_mode on each payment is the provider's record: live or test."},{"name":"Webhooks and events","description":"Register signed HTTPS endpoints for operation.completed, charging_session.status_changed, bill.finalized, display.delivery_changed and the charger events (station.connected, station.disconnected, station.booted, connector.status_changed, station.fault_opened, station.fault_cleared, meter.sampled; optional stations filter and meter sample interval), inspect delivery attempts and poll the same events by cursor with type and station_id filters. Requires webhooks:write to manage endpoints plus the read scope of each subscribed event. Deliveries are at-least-once with backoff; deduplicate by event id."},{"name":"External charging sessions","description":"Application-managed payment processors without installing an Ivora adapter. Ivora manages session identity, tokens, usage and immutable bills; your backend owns authorization, capture, refunds and recovery. Creation/start require explicit settlement:write permission. Optional settlement reports are application assertions, not verified transfers. See https://ivoracharge.com/developers/guides/settlement/external."},{"name":"Workspaces","description":"Manage the developer workspace and branding. A workspace is separate from CSMS tenant membership. Create it before using workspace-scoped sandbox resources."}]}