The Connect UI flow lets a user connect a vendor account without your application handling vendor-specific login. You create a session, send the browser to the returned URL, and get the user back once they're done. Everything in between is handled by clever-PV.
OCPP wallboxes and push meters still use the dedicated OCPP and push onboarding pages. Branding of the hosted pages is not configurable yet.
To implement vendor login yourself instead, see Device Onboarding Flow.
1. Create a session
Code
Code
Response 200 OK:
Code
| Field | Required | Notes |
|---|---|---|
vendorId | yes | Vendor from GET /v1/users/{userId}/vendors. |
redirectUri | yes | Where the browser returns on success. Register allowed URIs via the clever-PV Partner Portal. If redirectUri already has a query string, connectionId is appended with &. |
popup | no | Default false: full-page redirect back to redirectUri. true: Connect UI closes itself and notifies the opener via postMessage — see Popup mode. |
language | no | Supported languages: de, en, nl, fr, it, es, pt, el, fi, sv, hr, sk, sl, et, lv, lt, bg. |
- Auth: the current user's access token — a session is always tied to that user's home.
404if the user has no home.- To repair/re-authorize an existing connection, use
POST /v1/users/{userId}/connections/{connectionId}/sessionswith the same body — see Re-authorizing an existing connection.
Session lifetime
A session is single-use and expires after a few minutes — currently around 15 minutes for the
interactive steps (intro, credential form) and a shorter window of a few minutes for the OAuth
redirect leg. Treat the exact values as non-contractual; only "a few minutes, single-use" is
guaranteed. Create the session right before you open the browser window, never in advance, and
create a fresh one each time you start the flow. An expired, used, or unknown session renders the
session_expired error page.
Sessions that expire or that the user abandons are discarded server-side automatically: they have no effect on the user's home, there is nothing for you to clean up, and no endpoint to do so. A connection is only created (or, for re-authorization, updated) when the flow completes successfully.
2. Redirect the browser
Send the user's browser to connectUrl. Connect UI runs the vendor login and creates the
connection. You do not implement vendor-specific screens.
3. Handle the return
Redirect mode (popup: false, default)
On success the browser is sent to your redirectUri with the new connection id:
Code
On failure the user stays on Connect UI. There is no error redirect to your redirectUri and
no connectionId. Show a way to retry (create a new session) when the user comes back without one.
Popup mode
Set popup: true and open connectUrl with window.open so Connect UI can reach window.opener.
On success it posts { "status": "connected" } to the origin of your redirectUri and closes
the window. The message does not include connectionId — list the user's connections
(GET /v1/users/{userId}/vendors/connections) and take the new id.
Code
Verify event.origin against the Connect UI host (connectUrl's origin), not against your own
app origin. Failures stay on the Connect UI error page; the popup is not closed for you.
Failure pages
Connect UI shows a localized error page. The code in the path is:
code | When |
|---|---|
session_expired | Session unknown, already used, or timed out. Create a new session. |
user_denied | The user refused to authorize the connection. |
cookie_missing | A required cookie was blocked — common in in-app browsers. Ask the user to open the link in the device's default browser. See Embedded browsers. |
provider_error | The vendor login failed. Retry with a new session. |
partner_not_configured | No usable redirectUri on the session. Check the URI you sent. |
credentials_invalid | The user can correct the input and try again on the same page. This is not a terminal error page. |
Unknown codes render as 404 on Connect UI and are not a partner callback.
Note: Depending on the vendor's flow, a blocked cookie can also surface as
session_expiredinstead ofcookie_missing. If a user only fails inside an embedded browser but succeeds in the device's default browser, treat it as a cookie problem regardless of the code shown.
Embedded browsers (WebView / in-app)
Connect UI needs no third-party cookies. It only sets first-party cookies on its own domain
(Secure, SameSite=Lax), which the browser must send again when the vendor login redirects back.
For the flow to work in an embedded browser window (iOS WKWebView, Android WebView):
- Cookies must be enabled — no ephemeral/private data store, no cookie blocking.
- The entire flow, including the redirect back from the vendor login, must stay in the same browser instance.
- Do not recreate the WebView instance mid-flow.
SFSafariViewController (iOS) and Chrome Custom Tabs (Android) are more robust than a raw WebView
because they use the system cookie jar.
Additional guidance for apps:
- Use redirect mode (
popup: false). Popup mode relies onwindow.opener/postMessageand is not reliable inside embedded WebViews. - On failure there is no redirect to your
redirectUri— the user stays on the Connect UI error page. Give your embedded window its own close/cancel control. - The
redirectUrimust match a registered URI exactly (string match); register it via the clever-PV Partner Portal.
Re-authorizing an existing connection
When a device carries an authentication-required intervention, repair the underlying connection
with a session bound to it:
Code
Same body and flow as a regular session. One re-login covers all devices linked to that connection.
Finding the connectionId: it is part of GET /v1/users/{userId}/devices — not as a top-level
field, but inside the device's connect capability: capabilities[name="connect"].data.connectionId
(the vendor id is there too, and under model.vendor.id). For devices connected a long time ago the
field can be empty; fall back to GET /v1/users/{userId}/vendors/connections?vendorId={vendorId} —
with a single connection for that vendor the mapping is unambiguous.
GET /v1/users/{userId}/vendors/{vendorId}/devices also lists already-linked devices (with
available: false) and each entry carries its connectionId, so matching by externalId works —
but this list is read live from the vendor. When the connection's login has expired (the very case
that requires re-authorization), the affected connection returns no devices, so do not rely on this
endpoint for finding the connectionId to repair. If no linked device uses that connection, the same
call removes it (details); there is nothing left to
re-authorize, so start a regular session instead.
After the re-login: do not assume the authentication-required intervention clears on its own.
Re-fetch the device via GET /v1/users/{userId}/devices/{deviceId} and check that the intervention
is gone and core.connectivityStatus recovers. If it persists despite a successful re-login, that
is not something you can resolve via the API — contact your clever-PV partner manager with the
userId, deviceId, and timestamp.
Requirements
Register your client's allowed redirect URIs via the clever-PV Partner Portal before the first session. Multiple URIs are supported; an empty list means the connect flow is not available for that client yet.
After a successful return, continue with listing vendor devices and linking a device — Connect UI only creates the connection, not the clever-PV device.