Implementation Guide
Create an ongoing access flow, exchange the authorization code, and fetch financial data.
Getting Started
Three API calls to set up ongoing access to your user's financial data.
Create a Widget link for ongoing account access
Exchange the authorization code for an access token
Fetch accounts and transactions
1. Create the Widget link
POST https://api.finx-s.qwist.cloud/ongoing/access
{
"redirect_uri": "https://my-app.example.com/callback",
"user_id": "user_maria_mueller_42",
"language": "de",
"accounts": [
{ "id": "DE89370400440532013000" }
],
"account_types": ["Giro account"],
"allow_multi_selection": true,
"sync_period": 90,
"save_secrets": false
}Parameters:
| Parameter | Required | Description |
|---|---|---|
redirect_uri | ✅ | Where the user is returned after the flow. |
user_id | ✅ | Your unique identifier for this user. Allows multiple bank connections per user. |
language | Widget UI language. Options: de, en, es, fr, ar. Default: de. | |
accounts | Pre-fill the user's IBAN to skip bank selection. | |
account_types | Restrict to specific types (e.g. "Giro account"). Skips the type selection screen. | |
allow_multi_selection | true (default) lets the user connect multiple accounts. Set false to restrict to one. | |
sync_period | Days of history to fetch on first sync. Default: 90. | |
save_secrets | false (default): user sees a checkbox to choose credential storage. true: credentials always saved, autosync always enabled. |
Improve conversionPassing
accounts+account_typestogether gives the best completion rate: the user goes directly to SCA, skipping both bank selection and account type screens.
save_secrets behaviourWhen
save_secretsisfalse, the user is shown a "save credentials" checkbox during the Widget flow. If they uncheck it, autosync will not activate. If reliable autosync is required for your product, setsave_secrets: true- but review consent obligations with your legal team first.
Response:
{
"location": "https://widget.qwist.cloud/?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"id": "8f2e9d1c-4b3a-4721-bc8d-2e9f1a3d5c7b"
}Forward the user to location. The Widget handles bank selection, login, and SCA.
Looking for one-time access?
2. Exchange the authorization code
2. Exchange the authorization code
After the user completes the Widget flow, they are redirected to your redirect_uri with:
| Parameter | Description |
|---|---|
code | Authorization code valid for 1 hour. Present only on success. |
flow_id | Unique identifier for this flow. Matches the id from step 1. |
success | true if the user completed the flow. |
abort | true if the user cancelled. |
state | Your original state value, echoed back for session correlation. |
Example callback URL:
https://my-app.example.com/callback
?code=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
&flow_id=3ca31c37-986a-454e-ad64-8e97143c86bc
&success=true
&abort=false
&state=user_42_session_9f3a
If abort is trueThe user cancelled - no
codeis returned. Show a dismissal state and let the user retry. Do not attempt to exchange a missing code.
Exchange the code for tokens
POST https://api.finx-s.qwist.cloud/auth/token
// Request
{
"grant_type": "authorization_code",
"code": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"redirect_uri": "https://my-app.example.com/callback"
}// Response
{
"access_token": "AoFmNJLDTW8jQtGSJ1iZeeoLiwNZ2ihz3iiCHGpuvE439nppuY...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "RTfI2WNyK78NozupDH9ai8GPRbjjdVsXPPt...",
"scope": "accounts=ro balance=ro transactions=ro offline"
}Use the access_token as a Bearer token in the Authorization header for all subsequent requests. Store both tokens - you will need the refresh_token to keep access alive without re-asking the user.
| Token | Lifetime | Notes |
|---|---|---|
| Authorization code | 1 hour | Single use |
| Access token | 1 hour | Authorization: Bearer {token} |
| Refresh token | 90 days | Each use returns a new token - replace it immediately |
Token storageToken lengths vary. Allocate at least 2048 bytes per token field in your database - do not use fixed-size columns.
Refreshing the access token
Access tokens expire after 1 hour. For ongoing access, refresh server-side before expiry rather than waiting for a 401.
POST https://api.finx-s.qwist.cloud/auth/token
// Request
{
"grant_type": "refresh_token",
"refresh_token": "RTfI2WNyK78NozupDH9ai8GPRbjjdVsXPPt..."
}// Response
{
"access_token": "BpGnOKMEUX9kRuHTK2jZfpoMjxOa3jhQtjjDIHqwvF540oqqvZ...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "SUgJ3XOzL89PazvrEI0bj9HQSckkwWtYQQu...",
"scope": "accounts=ro balance=ro transactions=ro offline"
}
Replace the refresh token immediatelyEach call invalidates the previous
refresh_tokenand returns a new one. Persist the new token before using the newaccess_token- using the old refresh token will fail with401.
3. Fetch financial data
Use the access_token as a Bearer token. See Fetching Account & Transaction Data for the full endpoint reference.
