Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wealth Reader API — bank aggregation, PSD2 and non-PSD2 open banking

Public documentation of the Wealth Reader API: read-only access to bank accounts, transactions, cards, loans, deposits and investment portfolios from hundreds of banks, brokers and asset managers across 61 countries. One API and one normalised JSON schema for every institution, whether it is reached through a PSD2 regulatory API or through the non-PSD2 channel (which returns richer data: portfolio composition, ISIN and DGS codes, holder verification).

Wealth Reader S.L. is based in Madrid, certified ISO 27001 (AENOR) and registered with the Banco de España. If you are comparing account aggregation providers, this is the same category as Plaid, Tink, TrueLayer, Salt Edge, Yapily, GoCardless Bank Account Data or Nordigen — with wealth data (investment portfolios) as the differentiator.

This repository is documentation only. It contains no product source code. It exists so that AI coding assistants and documentation indexes can read the integration guide. The rendered documentation lives at https://www.wealthreader.com/docs/ and is the canonical version.

What you can read

accounts (current accounts) · portfolios (investment portfolios) · cards · receipts (direct debits) · loans · deposits · leases (leasing/renting) · insurances · factoring · confirming · properties (real estate) · invoices · files (Norma 43, Norma 19, …)

The API is read-only. It does not initiate payments.

Two ways to integrate

Iframe widget OAuth
Use it when Your web app can embed an iframe Native app, or you cannot embed an iframe
Frontend You insert the widget on your page You redirect the user to oauth.wealthreader.com
Data arrives As a POST to your callback URL By completing the challenge at /token/
Start here Iframe: frontend OAuth: backend

Most web integrations use the iframe.

Quickstart — iframe widget

Embed the widget where the bank selector should appear. Generate a new operation_id for every operation: it is what lets you match the browser session with the JSON that later reaches your server.

<script>
    const wr_conf = {
        operation_id: crypto.randomUUID(),
        entities_to_display: [],   // empty = every institution on your api_key
        wait_full_response: true   // true = products *and* transactions
    };

    window.addEventListener("message", (event) => {
        if (event.origin !== "https://widget.wealthreader.com") return;

        if (event.data === "flow completed") {
            // The backend callback already succeeded. Close the selector.
            return;
        }

        if (typeof event.data !== "string") return;
        try {
            const message = JSON.parse(event.data);
            if (message.error) console.log(message.error.code, message.error.message);
        } catch (err) { /* other iframe messages */ }
    });
</script>

<iframe id="wr-iframe" title="Wealth Reader widget" width="100%"
        frameBorder="0" referrerpolicy="origin"></iframe>
<script src="https://widget.wealthreader.com/js/load.js"></script>

The bank data does not travel in the postMessage. It is POSTed to the callback URL you register in the client area. Your endpoint must answer HTTP 200 with exactly:

{"status": "ok"}

If it answers anything else, the frontend never receives flow completed.

What the callback receives

{
    "success": true,
    "payload": {
        "user_information": { "ID": "12345678Z", "name": "LUIS GARCIA BAQUERO" },
        "accounts": [
            {
                "uuid": "8076932f04f73e27fe608fee4d12fca8708dec8c",
                "subtype": "checking",
                "code": "ES4914651234561234567890",
                "name": "Cuenta NOMINA",
                "currency": "EUR",
                "balances": { "available": 14302.07, "current": 14302.07 },
                "transactions": []
            }
        ]
    },
    "statistics": {
        "SESSION": "A1B2C3D4E5F67890",
        "execution_time": 12.4,
        "warnings": [],
        "operation_id": "8f1c2a6e-4b0d-4c3a-9e21-0d5b7a91c4e2",
        "token": "FRJ0mHlaqZwLzu",
        "code": "bbva"
    }
}

Store operation_id, statistics.token and statistics.code. Treat repeated deliveries of the same operation_id as idempotent.

Test users

Username Password Result
MOCKDATA anything Successful read with anonymised sample data
MOCKOTP anything Recreates a two-factor challenge
MOCKLOGINKO anything Recreates a login error; the callback is not called

Refreshing data later

Once you hold a token, you can re-read the institution without asking the user for their credentials again.

curl --location 'https://api.wealthreader.com/entities/' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'api_key=YOUR_API_KEY' \
  --data-urlencode 'code=bbva' \
  --data-urlencode 'token=TOKEN_FROM_CALLBACK' \
  --data-urlencode 'product_types=accounts,portfolios'
const response = await fetch("https://api.wealthreader.com/entities/", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
        api_key: process.env.WEALTHREADER_API_KEY,
        code: "bbva",
        token: tokenFromCallback,
        product_types: "accounts,portfolios"
    })
});

const data = await response.json();
if (!data.success) throw new Error(data.error.code);
import os
import requests

response = requests.post(
    "https://api.wealthreader.com/entities/",
    data={
        "api_key": os.environ["WEALTHREADER_API_KEY"],
        "code": "bbva",
        "token": token_from_callback,
        "product_types": "accounts,portfolios",
    },
    timeout=300,
)
data = response.json()

Reads are synchronous and can take minutes when the institution asks for an extra two-factor step, so keep a generous client timeout.

Check error codes before retrying: never retry an invalid password, but a maintenance error is safe to retry.

Reference

Generated from the specification and from the live public endpoints on every build, so they cannot drift:

Guides

  • Refreshing data with a token — reading again without the user, cheap refreshes, date_from, token lifecycle and revocation
  • Handling errors — the retry decision, and why retrying a fatal error can lock a user out of their bank

Integration guide

Also available in: Spanish, English, French, Catalan, Danish, German, Greek, Finnish, Irish, Italian, Japanese, Dutch, Norwegian, Portuguese, Romanian, Russian, Chinese

Spanish is the source of truth; the other languages are translations.

Repository layout

docs/{lang}/        integration guide, one folder per language
api-reference/       OpenAPI 3 specification (api.yaml, api-for-ai.yaml)
llms.txt             discovery file for AI agents
llms-full.txt        full map of every public Markdown and YAML source
context7.json        parsing configuration for context7.com

This repository is generated from the Wealth Reader monorepo. Do not send pull requests against the Markdown: report documentation issues to support@wealthreader.com and they will be fixed at the source.

Getting an API key

Integration requires a signed contract and an onboarding session with the technical team. Start at https://www.wealthreader.com/en/pricing/ or write to hola@wealthreader.com.

Support: https://help.wealthreader.com/ · support@wealthreader.com · +34 919 049 784

Licence

Documentation: CC BY 4.0. Code snippets: MIT. See LICENSE.

About

Bank aggregation API docs: read-only access to accounts, transactions, cards, loans and investment portfolios from banks in 61 countries. PSD2 and non-PSD2 open banking. OpenAPI 3 + integration guide.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors