HomeGuidesAPI Reference
Log In
Guides

Implementation Guide

Create an income report flow, exchange the authorization code, and fetch the verification report.

Getting Started

Three API calls to generate a disposable income report.

Step 1

Create a Widget link for income analysis

Step 2

Exchange the authorization code for an access token

Step 3

Fetch the income report


1. Create the Widget link

POST https://api.finx-s.qwist.cloud/onetime/income-report

{
  "redirect_uri": "https://my-app.example.com/callback",
  "language": "de",
  "reporting_period": 12,
  "accounts": [
    { "id": "DE89370400440532013000" }
  ],
  "account_types": ["Giro account"],
  "allow_multi_selection": false
}

Parameters:

ParameterRequiredDescription
redirect_uriWhere the user is returned after the flow.
reporting_periodMonths of transaction history to analyse. API minimum: 4. Recommended minimum for lending: 12. Default: 12. If the account is newer than this, the report covers the available history. Cannot be set at the same time as sync_period.
accountsPre-fill the user's IBAN to skip bank selection.
account_typesRestrict to specific account types (e.g. "Giro account"). Skips the account type selection screen.
allow_multi_selectiontrue lets the user connect multiple accounts (all are aggregated in the report). false restricts to one account.
languageWidget UI language. Options: de, en, es, fr, ar. Default: de.
📘

Single vs multi-account

For income and expense analysis, we recommend allow_multi_selection: false and explicitly passing the user's primary Giro account IBAN. This gives you a cleaner income picture from a single account, rather than aggregating across savings or credit card accounts.

Response:

{
  "location": "https://widget.qwist.cloud/?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "id": "f3a7d9c2-8e1b-4f5a-b2d6-9c4e7a1f3b8d"
}

Store the id - you need it to fetch the report in step 3. It is also returned as flow_id in the callback.


2. Exchange the authorization code

After successful completion of the flow, users are redirected to your specified redirect_uri with the following query parameters:

  • state: Your provided identifier to maintain session state and identify the returning user
  • success: Boolean indicating successful flow completion
  • code: Authorization code valid for 1 hour, used to obtain an access token (only present on successful completion)
  • abort: Boolean indicating if the user canceled the flow
  • flow_id: Unique identifier for accessing flow-specific resources
https://example.com/callback?code=eyJhbGciO...&state=7fe78733&success=true&flow_id=3ca31c37-...&abort=false

Exchanging the Code for Tokens

Request an access token by calling POST /auth/token with the following payload

// Request
{
  "grant_type": "authorization_code",
  "code": "eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp...",
  "redirect_uri": "https://my-app.example.com/callback"
}

// Response
{
  "access_token": "AoFmNJLDTW8jQtGSJ1iZeeoLiwNZ2ihz3iiCHGpuvE439nppuY...",
  "expires_in": 3600,
  "scope": "accounts=ro balance=ro transactions=ro offline",
  "token_type": "Bearer",
  "refresh_token": "RTfI2WNyK78NozupDH9ai8GPRbjjdVsXPPt..."
}

Using and Maintaining Tokens

  • Include the access_token in the Authorization header for all API requests
  • For ongoing access, store the refresh_token securely
  • Each refresh token usage returns a new refresh token that must replace the previous one
  • Access is revoked if:
    • No user activity occurs within 90 days
    • The refresh token isn't regularly renewed
📘

Token lengths

Token lengths can vary. Avoid fixed-size database fields for storing tokens. If a size limit is required, allocate at least 2048 bytes per token field.

Token lifetimes

TypeLifetime
Authorization code1 hour
Access token1 hour
Refresh token90 days


3. Fetch the income report

See Fetching your Income Report for the endpoint and response reference.