- Version: VERSIONTAG-draft
The SimpleFIN protocol allows users to share read-only financial data with third parties. It's similar to RSS, but for financial data.
Though intended mostly for banks, it can also be used for reward points or gift certificate balances (e.g. Frequent Flyer Miles, Amazon gift card balance, etc...)
Three parties are involved in SimpleFIN:
| Party | Description |
|---|---|
| User | A person using a web browser. They have an account at a bank or other institution. |
| Application | Third party software that wants read-only access to a User's financial data. |
| Server | A SimpleFIN Server operated by a bank or other financial institution. |
Application developers should start with the App Quickstart.
Banks or financial institutions wanting to host their own SimpleFIN Server should start at the Server Implementation Guide.
Users should visit the SimpleFIN Bridge.
This diagram shows how a User gives read-only bank account access to an App:
And this diagram shows how a User can revoke an App's access:
For optimal privacy, banks ought to implement SimpleFIN Servers. In some cases, where banks haven't yet implemented SimpleFIN, the SimpleFIN Bridge can be used.
This section is for application developers that want to integrate financial data (bank account balances/transactions) into their application.
If you are a programmer, and want programmatic access to your financial data, you're in the right place.
Connect your bank account to this app, by
<a href="https://bridge.simplefin.org/simplefin/create">clicking here.</a>
Here's an example HTML form that receives a SimpleFIN Token:
<form method="post">
SimpleFIN Token: <textarea name="token"></textarea>
<button type="submit">Connect Bank</button>
</form>
Securely store the Access URL for later use.
Here's a command line example. Obtain a SimpleFIN Token:
SIMPLEFIN_TOKEN="aHR0cHM6Ly9icmlkZ2Uuc2ltcGxlZmluLm9yZy9zaW1wbGVmaW4vY2xhaW0vZGVtbw=="
Base64 decode the SimpleFIN Token to get a URL:
CLAIM_URL=$(echo "${SIMPLEFIN_TOKEN}" | base64 --decode)
# https://bridge.simplefin.org/simplefin/claim/demo
Make a POST request to the decoded URL to get an Access URL:
ACCESS_URL=$(curl -X POST "${CLAIM_URL}")
# https://user123:pass456@bridge.simplefin.org/simplefin
Issue GET requests to the Access URL's /accounts resource to get account and transaction information.
Successful responses will be a JSON Account Set.
See GET /accounts for more information.
Request:
curl "${ACCESS_URL}/accounts"
Sample response:
{
"errors": ["You must reauthenticate."],
"accounts": [
{
"org": {
"domain": "mybank.com",
"sfin-url": "https://sfin.mybank.com"
},
"id": "2930002",
"name": "Savings",
"currency": "USD",
"balance": "100.23",
"available-balance": "75.23",
"balance-date": 978366153,
"transactions": []
}
]
}
The following checklists can help make sure your SimpleFIN-capable application is implemented correctly:
The application:
- Handles a 403 response when claiming an Access URL.
- When claiming an Access URL fails, notifies the customer that the token may be compromised so they can disable the token.
- Only makes requests to SSL/TLS URLs (i.e. HTTPS and never HTTP).
- Stores Access URLs at least as securely as the user's financial data.
- Handles a 403 response from
/accounts. - Displays error messages from
/accountsto the user. - Sanitizes all error messages from
/accountsthat are displayed to the user. - Verifies all SSL/TLS certificates when making HTTPS requests.
The application:
- Handles custom currencies.
| Attribute | Type | Required | Description |
|---|---|---|---|
| errors | array | yes | Array of strings suitable for displaying to a user. |
| accounts | array of Accounts | yes | List of accounts. |
{
"errors": [],
"accounts": [
{
"org": {
"domain": "mybank.com",
"sfin-url": "https://sfin.mybank.com"
},
"id": "2930002",
"name": "Savings",
"currency": "USD",
"balance": "100.23",
"available-balance": "75.23",
"balance-date": 978366153,
"transactions": [
{
"id": "12394832938403",
"posted": 793090572,
"amount": "-33293.43",
"description": "Uncle Frank's Bait Shop",
}
],
"extra": {
"account-open-date": 978360153,
}
}
]
}
| Attribute | Type | Required | Description |
|---|---|---|---|
| org | Organization | yes | Organization from which this account originates. |
| id | string | yes | String that uniquely identifies the account within the organization. It is recommended that this id be chosen such that it does not reveal any sensitive data (login information for the bank's web banking portal, for instance). |
| name | string | yes | A name that uniquely describes an account among all the users other accounts. This name should be chosen so that a person can easily associate it with only one of their accounts within an organization. |
| currency | string | yes | If the currency is a standard currency, this is the currency code from the official ISO 4217. For example "ZMW" or "USD". If this is a custom currency, see the Custom Currencies section below. |
| balance | numeric string | yes | The balance of the account as of balance-date. |
| available-balance | numeric string | optional | The available balance of the account as of balance-date. This may be omitted if it is the same as balance. |
| balance-date | UNIX epoch timestamp | yes | The timestamp when the balance and available-balance became what they are. |
| transactions | array of Transactions | optional | List of a subset of Transactions for this account, ordered by posted. |
| extra | object | optional | This optional attribute may be used to include extra account-specific data that is not defined in this standard. It is up to the Server to decide whether or not to include data in here. |
{
"org": {
"domain": "mybank.com",
"sfin-url": "https://sfin.mybank.com"
},
"id": "2930002",
"name": "Savings",
"currency": "USD",
"balance": "100.23",
"available-balance": "75.23",
"balance-date": 978366153,
"transactions": [
{
"id": "12394832938403",
"posted": 793090572,
"amount": "-33293.43",
"description": "Uncle Frank's Bait Shop",
}
],
"extra": {
"account-open-date": 978360153,
}
}
SimpleFIN supports custom currencies such as: Frequent Flyer Miles, Rewards Points, brownie points, etc...
Custom currencies are identified by a unique URL. When an HTTP GET request is made to the URL, it should return a JSON object with the following attributes:
| Attribute | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Human-readable name of the currency. |
| abbr | string | yes | Human-readable short name of the currency. |
The following Account's currency is https://www.example.com/fake-currency
{
...
"id": "2930002",
"name": "Savings",
"currency": "https://www.example.com/flight-miles",
"balance": "100.23",
"available-balance": "75.23",
"balance-date": 978366153,
"transactions": []
}
Making a request to the currency URL:
curl https://www.example.com/flight-miles
Returns the following:
{
"name": "Example Airline Miles",
"abbr": "miles"
}
| Attribute | Type | Required | Description |
|---|---|---|---|
| id | string | yes | An ID that uniquely describes a transaction within an Account. An organization may reuse transaction ids for different accounts, but may never reuse a transaction id within an account. |
| posted | UNIX epoch timestamp | yes | This is when the transaction posted to the account. If the transaction is pending, this may be 0. |
| amount | numeric string | yes | Amount of transaction. Positive numbers indicate money being deposited into the account. |
| description | string | yes | A human-readable description of what the transaction was for. |
| transacted_at | UNIX epoch timestamp | optional | This is when the transaction happened. |
| pending | boolean | optional | true indicates that this transaction has not yet posted. Default is false (or absent), meaning the transaction has posted. |
| extra | object | optional | This optional attribute may be used to include extra transaction-specific data that is not defined in this standard. It is up to the Server to decide whether or not to include data in here. |
{
"id": "12394832938403",
"posted": 793090572,
"amount": "-33293.43",
"description": "Uncle Frank's Bait Shop",
"pending": true,
"extra": {
"category": "food"
}
}
| Attribute | Type | Required | Description |
|---|---|---|---|
| domain | string | maybe | Domain name of the financial institution. |
| sfin-url | string | yes | Root URL of organization's SimpleFIN Server |
| name | string | maybe | Human-friendly name of the financial institution. |
| url | string | no | Optional URL of financial institution |
| id | string | no | Optional ID for the financial institution. The ID must be unique per SimpleFIN server, but it is not guaranteed that IDs are globally unique. Prefer domain as a globally unique ID for each institution |
"org": {
"domain": "mybank.com",
"name": "My Bank",
"sfin-url": "https://sfin.mybank.com"
}
Following are all 4 HTTP endpoints a SimpleFIN Server must implement.
ROOT="https://bridge.simplefin.org/simplefin"
Used by Applications to find out what versions of the SimpleFIN Protocol the server supports. The strings returned must be in MAJOR.MINOR.FIX or MAJOR.MINOR format.
Note: as this specification is still in draft, most servers will report 1.0 but may not yet support all things from the draft specification.
GET /info
| Attribute | Description |
|---|---|
| versions | An array of version string prefixes that this server supports. |
Request:
curl https://bridge.simplefin.org/simplefin/info
Response:
{
"versions": ["1.0"],
}
- Authenticates the user
- Guides the user to create a SimpleFIN Token.
- Tells the user to give the SimpleFIN Token to the application requesting it.
This process could happen all at once with a single response (if the user is already authenticated) or it could be more involved. Either way, the end result is a copyable SimpleFIN Token.
GET /create
To connect your bank to this application,
<a href="https://bridge.simplefin.org/simplefin/create">click here</a>
An example SimpleFIN Token looks like this:
aHR0cHM6Ly9icmlkZ2Uuc2ltcGxlZmluLm9yZy9zaW1wbGVmaW4vY2xhaW0vZGVtbw==
POST /claim/:token
| Parameter | Description |
|---|---|
| :token | A one-time use code embedded within the SimpleFIN Token. |
Response is an Access URL, which is just a URL with included Basic Auth credentials.
| Code | Description |
|---|---|
| 200 | Successful response |
| 403 | The claim token either does not exist or has already been used claimed by someone else. Receiving this could mean that the user's transaction information has been compromised. |
The following example uses a demo token that can be reused:
TOKEN="aHR0cHM6Ly9icmlkZ2Uuc2ltcGxlZmluLm9yZy9zaW1wbGVmaW4vY2xhaW0vZGVtbw=="
Decode the token:
DECODED_TOKEN=$(echo "${TOKEN}" | base64 -D)
Claim the Access URL associated with this SimpleFIN Token:
ACCESS_URL=$(curl -X POST "${DECODED_TOKEN}")
# https://demo:demo@bridge.simplefin.org/simplefin
GET /accounts
| Parameter | Required | Description |
|---|---|---|
| start-date | optional | If given, transactions will be restricted to those on or after this Unix epoch timestamp. |
| end-date | optional | If given, transactions will be restricted to those before (but not on) this Unix epoch timestamp. |
| pending | optional | If pending=1 is provided, pending transactions will be included (if supported). By default, pending transaction are NOT included. |
| account | optional | If given, only return information related to the given account id. May be specified multiple times. |
| balances-only | optional | If balances-only=1 is provided, no transaction data is returned. |
HTTP Basic Authentication using credentials obtained from the POST /claim/:token endpoint are used.
A successful response will be a JSON Account Set.
| Code | Description |
|---|---|
| 200 | Successful response |
| 402 | Payment required |
| 403 | Authentication failed. This could be because access has been revoked or if the credentials are incorrect. |
curl "https://demo:demo@bridge.simplefin.org/simplefin/accounts?start-date=978360153"
Sample response:
{
"errors": [],
"accounts": [
{
"org": {
"domain": "mybank.com",
"sfin-url": "https://sfin.mybank.com"
},
"id": "2930002",
"name": "Savings",
"currency": "USD",
"balance": "100.23",
"available-balance": "75.23",
"balance-date": 978366153,
"transactions": []
}
]
}