PSD2 Consent Flow
Reading live bank data is governed by PSD2: access must be explicitly authorized at the bank before Lexabit can read the accounts. That authorization is captured through a browser redirect flow. This page explains the flow end to end; for the surrounding account-tracking workflow (activating a user, tracking accounts, syncing transactions) see the Account Tracking guide.
Technically the flow is the same regardless of why access is legitimate: whoever holds the right to the accounts authenticates at the bank and approves. Usually that is the account holder themselves; it can also be another party acting with the account holder's authorisation, or with an independent legal mandate, using the access the bank has granted them. Which party may lawfully do so is governed by the applicable legal framework — not by this API. This is also distinct from platform authentication: a valid Lexabit token never substitutes for the bank-side authorization.
Why there's a redirect
A bearer token proves who your user is to Lexabit. It does not prove the account holder has authorized bank access — only the bank can capture that, by having the holder log in and approve. So the flow bounces the holder's browser to their bank and back:
your app Lexabit API bank
│ create consent │ │
├──────────────────▶│ (status: pending) │
│ initiate-redirect │ │
├──────────────────▶│ │
│◀── authorization URL │
│ send holder's browser ─────────────────────▶│ holder logs in & approves
│ │ callback (bank → API) │
│ │◀─────────────────────────┤
│ check status │ (status: valid) │
├──────────────────▶│ │
Step 1 — Create the consent
State the integration, the purpose, and how long the consent should last. It starts pending and unusable until approved.
curl -X POST "https://api.lexabit.com/accounttracking/v1/consents" \
-H "Authorization: Bearer $LEXABIT_TOKEN" \
-H "X-Scope: 42" \
-H "Content-Type: application/json" \
-d '{ "integrationName": "EnableBanking", "purpose": "account_access", "expiryDays": 90 }'
{
"data": {
"id": "cn-88f1-…",
"integrationName": "EnableBanking",
"purpose": "account_access",
"status": "pending",
"isValid": false
},
"meta": { "requestId": "b2a1…" }
}
purpose is one of account_access, transaction_history, balance_inquiry,
or credit_check. Keep the returned id — it identifies the consent for every
later step.
Step 2 — Get the authorization URL
Ask the API to initiate the redirect. The response contains the bank authorization URL the account holder must visit.
curl -X POST \
"https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/initiate-redirect" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
Send the account holder's browser to that URL (redirect them, or open it in a popup). Don't try to call it server-to-server — it's an interactive bank login.
Step 3 — The bank calls back
After the holder approves, the bank redirects to Lexabit's callback for that integration:
GET /accounttracking/v1/consents/callback/{integration}
You don't call this yourself — the bank does, as the final hop of the redirect. Lexabit processes it, links the approval to the consent you created, and flips the consent to valid. Configure where the holder lands afterwards (your success page) as part of your integration setup.
Step 4 — Confirm the consent is live
Before relying on the consent, verify it:
curl "https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/status" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
A valid consent reports status: "valid" and isValid: true. You can also
validate it for a specific operation before using it:
curl -X POST "https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/validate" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
Once valid, continue with tracking accounts and syncing transactions.
Lifecycle: renew, revoke, expire
A consent moves through these states:
pending ──▶ valid ──▶ expired (time runs out)
│ │
│ └─────▶ revoked (you or the holder revokes)
└────────────────▶ (never approved)
- pending — created, awaiting the holder's approval at the bank.
- valid — approved and usable (
isValid: true). - expired — passed its
expiryDayswindow; renew to restore access. - revoked — explicitly cancelled; not reusable.
Consents are time-boxed (expiryDays) and must be maintained:
| Action | Endpoint |
|---|---|
| Days left | GET /accounttracking/v1/consents/{consent}/remaining-days |
| Renew (replaces with a fresh consent) | POST /accounttracking/v1/consents/{consent}/renew |
| Revoke explicitly | POST /accounttracking/v1/consents/{consent}/revoke |
| Batch-revoke expired | POST /accounttracking/v1/consents/revoke-expired |
Renewing generally requires the holder to re-approve through the same redirect, so prompt them before expiry rather than after access has already broken.
Sharing a consent across scopes
A consent is owned by the scope that created it, but can be shared so another team or entity can use the same bank access without a second approval:
# Share with another scope
curl -X POST "https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/visibility" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42" \
-H "Content-Type: application/json" -d '{ "scopeType": "team", "scopeId": "tm-01-…" }'
GET …/visibility lists who it's shared with; DELETE …/visibility revokes a
share.
Where to go next
- Account Tracking guide — the full workflow
- API Reference → Account Tracking — every consent endpoint