Skip to navigation

Authentication & keys

Your secret opens the API, the widget signs in on its own, a key you mint per session keeps the webhooks yours — and, with recurring access, a token key that is only yours

View as Markdown

Three different things are protected in a Financial Rider integration, and each has its own key. Your backend proves who it is with your application secret. Your customer’s browser talks to the widget with a token of the session’s own. And what our servers push to yours can be encrypted with a key only you hold.

KeyWho holds itWhat it protects
Application secret (X-APP-SECRET)your backendevery call to this API: creating a session, reading it, cancelling it, deleting it, downloading its attachmentsrequired
The session’s tokenthe widget, inside widget_urlyour customer’s journey through that one sessionissued with the session
aes_keyyou, per sessionthe data of every webhook the session sendsoptional, recommended
token_id + token_keyyou, per connectionrecurring access: reading a bank again with nobody presentonly with recurring access

The application secret

Every call carries it:

X-APP-SECRET: <your application secret>

The secret belongs on your server and nowhere else. It can act for any of your customers and read every record extracted under your application. It must never reach a browser, a mobile binary, a front-end bundle or anything a user can open — there is no client-side use of these APIs, by design.

Secrets are issued per application in the console, and an application can hold more than one. That is what makes rotation uneventful: mint the new secret, deploy it, then revoke the old one. Revoking a secret never touches the application, its sessions, its executions or its data. Security & keys is the screen.

When authentication fails, the answer is an HTTP status and a stable detail code — branch on the code, show your own message:

StatusdetailWhat happened
401not_authenticatedThe header was missing.
401invalid_application_secretThe value is not a well-formed secret.
401unauthorizedIt is well formed but unknown.
401app_secret_revokedIt was valid and has been revoked.
403app_pendingThe application exists but is not approved yet.
403app_lockedThe application has been locked. Contact support.
403app_archivedThe application has been archived.

Sandbox or production is decided per session, with settings.sandbox, and a production session needs your application in production and holding its capability — Sandbox and production has what that takes. The base URLs, the error shape and the headers every response carries are the same for every API: Using the API.


The widget signs in on its own

The widget_url that Create Session returns carries a token of its own, valid for that one session. It is what lets your customer’s browser talk to us while they go through the widget — it is not your secret, and nothing in it reaches your application’s other sessions or the API you call from your backend. Treat it as you would the session itself: it goes to the customer it was created for, and to nobody else.


The session key: aes_key

A key you mint, once per session, so that what our servers push to yours is readable only by you. It is optional and recommended: 32 random bytes, Base64-encoded, sent once in settings.aes_key when you create the session.

With an aes_keyWithout one
The webhooksEvery event the session sends carries its data, encrypted under your key as aes::Base64(IV + ciphertext + tag) — AES-256-GCM.They still tell you what happened, and carry no data at all.
The resultsRead with your secret, as always.Read with your secret — the only way to get them.

The key encrypts the webhooks, and only the webhooks. The results endpoint and the attachment downloads answer to your application secret, over TLS; they are never encrypted with the session key. That is why a webhook without a key carries nothing: the one channel that reaches a public endpoint of yours is the one that must not carry records in the clear.

What follows from it:

  • Mint a fresh key for every session. One key per session keeps one session’s payloads from opening another’s.
  • Keep it until the session’s last webhook. You need it to decrypt each one, the final event included. Store it server-side, beside the session_id.
  • We never give it back. It is not in Get Session Settings, nor in any other answer — losing it means reading that session’s results from the results endpoint instead.
Minting a key
openssl rand -base64 32
Python
import base64, os
aes_key = base64.b64encode(os.urandom(32)).decode()
Node.js
const aesKey = require('node:crypto').randomBytes(32).toString('base64');

The decryption — strip aes::, split IV, ciphertext and tag, open with AES-256-GCM — is on the Payload Encryption guide, with an interactive sandbox to test it and working code in Node.js, Python and Java.


Nothing to encrypt towards us

Your customer types their credentials into the widget, not into your systems, so a flow’s calls carry nothing for you to encrypt. The application’s inbound key pair — the one Direct Executions uses so that the credentials you send are unreadable on the way — plays no part in integrating a flow.

Without a key, Get Session Results is how the results reach you; with one, the final webhook brings them too. Payload Decryption, on the overview, has the envelope of this flow’s events.


Recurring access: the token key

With recurring access, each bank your customer connects is exchanged for a token, on the Direct Executions API and with your application secret: Exchange a ticket returns a token_id and a token_key.

  • token_key is your half of the access, and only yours: we keep the credentials encrypted and a verifier of your key, never the key. Store it as you would a password — encrypted at rest, out of your logs. It is shown once, and replaced on every renewal.
  • It is not an encryption key you use. You never encrypt anything with it: it is one input to the derivation that opens the stored credentials, at the moment of a refresh and inside our runtime. Credential Tokenization explains the design, and what losing it means.
  • token_id never changes for the life of a connection — not on a refresh, not on a renewal — so it is the key of your list of connections. Your list of connections explains it.