Account Tracking
Account Tracking connects to a customer's bank under PSD2, then keeps their accounts, transactions, and counterparts in sync. Because it reads live bank data, it has one extra requirement over the rest of the API: an explicit consent grant authorized at the bank — by the account holder or another party entitled to access the accounts — obtained through a bank redirect.
This guide covers the whole flow end to end. For the consent redirect mechanics in detail, see PSD2 Consent Flow.
The big picture
register ──▶ create consent ──▶ bank redirect ──▶ callback
│ │
▼ ▼
(user is list available
activated) accounts for
the consent
│
▼
track account ──▶ sync transactions ──▶ read
Each step is a normal scoped API call (send Authorization + X-Scope), except
the redirect itself, which happens in the account holder's browser.
The setup half of this flow — registering for tracking, creating a bank
consent, adding an account, and triggering a transaction sync — is designed for
a signed-in human user. Called with an App token (a connector-born App, a
delegated agent, an API key), these endpoints return 403 with
error.code = "user_context_required". For now, accounts are registered,
consented, and tracked by the customer in the Lexabit Portal.
What an App or agent should do instead: work with the accounts that already
exist — GET /accounttracking/v1/accounts, then read each account's
transactions, stats, and sync status. Accounts can be configured to update
automatically several times a day, so tracked accounts stay in sync even
though manual sync isn't available to machine actors — freshness comes from
those scheduled updates and the customer's own activity, and there is nothing
you need to trigger. Machine-initiated account setup — where your integration starts the
process and hands the account holder a link for the bank step — needs more work
on our side and is planned.
1. Activate the user for account tracking
A user must be registered for account tracking before they can hold consents or track accounts. Check status, then register if needed:
# Is the current user active?
curl "https://api.lexabit.com/accounttracking/v1/active" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
# Register them
curl -X POST "https://api.lexabit.com/accounttracking/v1/users" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
2. Discover which banks are available
curl "https://api.lexabit.com/accounttracking/v1/banks?country=NO" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
GET /accounttracking/v1/supported-countries lists which countries are
available at all. Note the bankId of the bank you want — you'll need it when
tracking an account.
3. Create a consent
A consent records the account holder's permission for your integration to access their bank, for a stated purpose and duration.
- curl
- Python
- JavaScript
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
}'
import os, requests
resp = requests.post(
"https://api.lexabit.com/accounttracking/v1/consents",
headers={
"Authorization": f"Bearer {os.environ['LEXABIT_TOKEN']}",
"X-Scope": "42",
},
json={"integrationName": "EnableBanking", "purpose": "account_access", "expiryDays": 90},
)
resp.raise_for_status()
consent = resp.json()["data"]
consent_id = consent["id"]
const resp = await fetch("https://api.lexabit.com/accounttracking/v1/consents", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LEXABIT_TOKEN}`,
"X-Scope": "42",
"Content-Type": "application/json",
},
body: JSON.stringify({ integrationName: "EnableBanking", purpose: "account_access", expiryDays: 90 }),
});
const consent = (await resp.json()).data;
const consentId = consent.id;
201 Created:
{
"data": {
"id": "cn-88f1-…",
"integrationName": "EnableBanking",
"purpose": "account_access",
"status": "pending",
"isValid": false,
"expiresAt": null,
"remainingDays": "90"
},
"meta": { "requestId": "b2a1…" }
}
The consent starts pending / isValid: false — it isn't usable until the
account holder approves it at their bank.
4. Send the account holder to their bank
Ask the API for a redirect URL and send the user's browser there. When they finish at the bank, the bank calls your integration's callback and the consent flips to valid.
curl -X POST \
"https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/initiate-redirect" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
The response contains the bank authorization URL. The mechanics — redirect URL,
the GET /accounttracking/v1/consents/callback/{integration} callback, and
verifying the result — are covered step by step in
PSD2 Consent Flow.
You can confirm the consent is live before continuing:
curl "https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/status" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
5. Track an account
With a valid consent, list the accounts it exposes, then track the one(s) you want:
# Accounts available under this consent
curl "https://api.lexabit.com/accounttracking/v1/consents/cn-88f1-…/accounts" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
# Start tracking one
curl -X POST "https://api.lexabit.com/accounttracking/v1/accounts" \
-H "Authorization: Bearer $LEXABIT_TOKEN" \
-H "X-Scope: 42" \
-H "Content-Type: application/json" \
-d '{ "bankId": "NO-DNB", "countryCode": "NO", "accountType": "company" }'
accountType is private, company, or payment. Now GET /accounttracking/v1/accounts lists everything you're tracking in the current
scope.
6. Sync and read transactions
Tracking an account doesn't continuously stream data — you trigger a sync, then read. Transactions are cursor-paginated:
# Pull the latest transactions from the bank
curl -X POST "https://api.lexabit.com/accounttracking/v1/accounts/{id}/sync-transactions" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
# Read them back, filtered by date
curl "https://api.lexabit.com/accounttracking/v1/accounts/{id}/transactions?filter[fromDate]=2026-06-01&perPage=100" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
Check GET /accounttracking/v1/accounts/{id}/sync-status to see whether a sync
is still running.
7. Counterparts (who's on the other side)
Lexabit groups transactions by counterpart — the party a transaction is with. You can list an account's counterparts, bind a transaction to one, and even link counterparts into parent/child families:
curl "https://api.lexabit.com/accounttracking/v1/accounts/{accountId}/counterparts" \
-H "Authorization: Bearer $LEXABIT_TOKEN" -H "X-Scope: 42"
See the API Reference → Account Tracking for the full counterpart toolset (aliasing, consolidation, entity binding, family trees).
Managing the consent lifecycle
- Renew before expiry:
POST /accounttracking/v1/consents/{consent}/renew - Revoke when done:
POST /accounttracking/v1/consents/{consent}/revoke - Check remaining validity:
GET /accounttracking/v1/consents/{consent}/remaining-days
Where to go next
- PSD2 Consent Flow — the redirect in detail
- API Reference → Account Tracking — every endpoint and field