Request an AIS access token

An AIS access token authenticates your calls to Fintecture's account information (AIS) endpoints. Because account data belongs to the end user, AIS uses the OAuth 2.0 authorization code flow: the user first authenticates with their bank, you receive a code, and you exchange it for an access token — plus a refresh token to renew access without sending the user through the flow again.

How it works

  1. Create a Fintecture account
  2. Register a client application and get the credentials (i.e. the app_id and app_secret) associated to it
  3. Request the AIS Connect URL and redirect the user to it
  4. On redirection back to your app, extract the code query parameter
  5. Exchange the code for an access token with the AIS scope
  6. Use the returned access_token as a Bearer token on every bank account endpoint
  7. Before it expires, get a new access token with the refresh token
❗️

Keep your app_secret secret

Exchange codes and refresh tokens from your backend only. Never embed the app_secret (or a valid token) in a browser, mobile app, or public repository.

1. Get an authorization code

Request the AIS Connect URL and redirect the user to it. The user authenticates with their bank and consents to share their account data. When they are redirected back to your redirect_uri, read the code query parameter — this is the value you exchange in the next step.

2. Exchange the code for a token

Call POST /oauth/accesstoken with your Base64-encoded credentials in the Authorization header (base64({app_id}:{app_secret})) and a form-encoded body:

curl -X POST "https://api.sandbox.fintecture.com/oauth/accesstoken" \
  -H "Authorization: Basic $(echo -n "$APP_ID:$APP_SECRET" | base64 | tr -d '\n')" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=$CODE" \
  -d "scope=AIS"
const basic = Buffer.from(`${APP_ID}:${APP_SECRET}`).toString('base64');

const response = await fetch('https://api.sandbox.fintecture.com/oauth/accesstoken', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${basic}`,
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code,               // the code received on redirection
    scope: 'AIS',
  }),
});

const { access_token, refresh_token, expires_in } = await response.json();
import base64

import requests

basic = base64.b64encode(f"{app_id}:{app_secret}".encode()).decode()

response = requests.post(
    "https://api.sandbox.fintecture.com/oauth/accesstoken",
    headers={"Authorization": f"Basic {basic}"},
    data={"grant_type": "authorization_code", "code": code, "scope": "AIS"},
)
response.raise_for_status()
tokens = response.json()
📘

Sandbox vs production

The examples above target the sandbox. For production, use https://api.fintecture.com — and remember that each environment has its own app_id / app_secret.

3. Read the response

{
  "token_type": "Bearer",
  "access_token": "eyJhbGciOiJub25lIn0.eyJleHAiOjE1MTQwODA0MjQsI",
  "expires_in": 599,
  "refresh_token": "4n7WgFIi1Pq5texGOza4tMGBZbnIfd5vrQXPs7E7hg3L"
}
FieldDescription
token_typeAlways Bearer
access_tokenThe token to send on every AIS call
expires_inRemaining validity, in seconds
refresh_tokenStore it securely — used to get new access tokens without user interaction

4. Use the token

Send the token in the Authorization header of every bank account endpoint:

Authorization: Bearer eyJhbGciOiJub25lIn0.eyJleHAiOjE1MTQwODA0MjQsI
📘

Most AIS endpoints also require a request signature on top of the Bearer token. See HTTP Signature.

5. Renew with the refresh token

Track expires_in and, before the access token expires, call POST /oauth/refreshtoken — same Authorization: Basic header, no user interaction needed:

curl -X POST "https://api.sandbox.fintecture.com/oauth/refreshtoken" \
  -H "Authorization: Basic $(echo -n "$APP_ID:$APP_SECRET" | base64 | tr -d '\n')" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=$REFRESH_TOKEN"

The response contains a fresh access_token. Keep using your stored refresh_token for subsequent renewals.

Troubleshooting

StatusMost likely causeFix
400 bad_requestMissing/invalid grant_type, code or scope, or body not form-encodedSend Content-Type: application/x-www-form-urlencoded with the three fields above
401 unauthorizedWrong app_id:app_secret, expired/already-used code, or credentials from the other environmentRe-encode the header; restart the connect flow to get a fresh code
403 forbiddenApplication not allowed to use the AIS scopeCheck your application's products in the Console, or contact support

Every error response contains a log_id — include it when you contact support so we can trace the exact call.

Recipe