SimpleFIN API

SimpleFIN is another way to get bank data into monetr without going through Plaid. You get a setup token from your SimpleFIN Bridge, hand it to monetr, and monetr trades it for an access URL that it keeps in its secret storage.

Enabled by default

These endpoints are on by default, out of the box monetr only talks to bridge.simplefin.org. If simpleFin.enabled is false in your configuration, or simpleFin.allowedHosts is empty, they return 404 with "SimpleFIN is not enabled on this server".

There are two objects involved: the SimpleFIN link, which holds the connection to your Bridge, and the ordinary monetr link that owns the bank accounts. Creating a SimpleFIN link is the first step, it starts out pending.

AttributeTypeDescription
simpleFinLinkIdstring (ulid)Identifies the connection.
namestringWhat you called it.
apiUrlstringThe SimpleFIN server monetr talks to, with the credentials taken out.
statusstringpending, active, deactivated or error.
lastErrorsarray, nullableThe errors SimpleFIN sent back on the last request, each with a code, message, connectionId and simpleFinId. SimpleFIN wants you to see these.
lastManualSynctimestamp, nullableWhen someone last forced a sync.
lastSuccessfulUpdatetimestamp, nullableWhen data last actually came through.
lastAttemptedUpdatetimestamp, nullableWhen monetr last tried to sync.
createdAttimestampWhen it was created.
createdBystring (ulid)The user who set it up.
updatedAttimestampWhen the record last changed.
deletedAttimestampWhen it was removed. Absent on live connections.

The access URL has your SimpleFIN username and password in it, so it's never in the response. It goes into monetr's secret storage when the setup token is claimed and doesn't come back out.

Statuses

StatusMeaning
pendingCreated but not attached to a monetr link yet. Nothing syncs. Abandoned pending connections may get cleaned up, along with their access URL.
activeAttached and syncing on a schedule.
deactivatedTurned off by hand or on its way out. Background jobs skip it.
errorSimpleFIN said the access URL doesn't work anymore, like the token was revoked or the Bridge needs to be paid for. monetr stops syncing it on its own because every request counts against your daily quota. A successful manual sync moves it back to active.

The SimpleFIN bank account object

These are the accounts monetr found on your SimpleFIN Bridge. They aren't monetr bank accounts yet, they're candidates.

AttributeTypeDescription
simpleFinBankAccountIdstring (ulid)Identifies the candidate account.
simpleFinLinkIdstring (ulid)The connection it came from.
simpleFinIdstringThe account's ID on the SimpleFIN side. Not a monetr ULID, and it's only unique within its connectionId.
connectionIdstringThe SimpleFIN connection (the bank login on your Bridge) the account belongs to.
namestringThe account name.
institutionNamestringThe bank, according to SimpleFIN. If SimpleFIN didn't say which connection it's from, this is just the account name.
currencystringISO 4217 code. Accounts SimpleFIN reports in a custom currency, like reward points, are skipped and never show up here.
statusstringactive once you've added it, inactive if you haven't or you archived it.
currentBalanceintegerThe balance according to SimpleFIN, in the currency's smallest unit.
availableBalanceintegerThe available balance, in the currency's smallest unit. SimpleFIN doesn't always send one, when it doesn't this is the same as currentBalance.
createdAttimestampWhen monetr first saw it.
createdBystring (ulid)The user whose refresh discovered it.
updatedAttimestampWhen the record last changed.
deletedAttimestampWhen it was removed. Absent normally.

GET List SimpleFIN connections

Returns every SimpleFIN connection on your account.

In the app: Not used by the app yet.

GET /api/simplefin/link

Auth: API key, subscription required.

Example

curl --request GET \
  --url "https://my.monetr.local/api/simplefin/link" \
  --user "$MONETR_API_KEY_ID:$MONETR_API_KEY_SECRET"
[
  {
    "simpleFinLinkId": "sfx_01j7k3m9pw2rx8vt5nqdbe4chz",
    "name": "SimpleFIN Bridge",
    "apiUrl": "https://bridge.simplefin.org/simplefin",
    "status": "active",
    "lastErrors": null,
    "lastManualSync": "2024-08-28T19:41:02.118Z",
    "lastSuccessfulUpdate": "2024-08-29T06:00:14.772Z",
    "lastAttemptedUpdate": "2024-08-29T06:00:14.772Z",
    "createdAt": "2024-07-19T14:22:38.905Z",
    "createdBy": "user_01fpwx3sdm7kb1s0jbrbvbdw4c",
    "updatedAt": "2024-08-29T06:00:14.772Z"
  }
]

GET Get a SimpleFIN connection

Returns one connection.

In the app: Not used by the app yet.

GET /api/simplefin/link/:simpleFinLinkId

Auth: API key, subscription required.

Path parameters

AttributeTypeRequiredDescription
simpleFinLinkIdstring (ulid)YesThe connection you want.

Errors

StatusWhen
400simpleFinLinkId is malformed.
404No such connection, or SimpleFIN isn't enabled on this server.

POST Create a SimpleFIN connection

Claims a setup token and stores the access URL SimpleFIN gives back. Unlike Lunch Flow this does talk to SimpleFIN right away, because a setup token is only good for one claim.

In the app: Not used by the app yet.

POST /api/simplefin/link

Auth: API key, subscription required.

Body

AttributeTypeRequiredDescription
namestringYesWhat to call this connection.
setupTokenstringYesThe setup token from your SimpleFIN Bridge, up to 2048 characters. See the rules below.

The setup token is checked against a few rules:

  • It has to be a real setup token, which is a claim URL that's been base64 encoded.
  • The claim URL has to be https and on the server's allow list, set with simpleFin.allowedHosts. That's just bridge.simplefin.org unless the operator changed it.
  • The access URL SimpleFIN sends back has to follow the same rules. If it points somewhere that isn't allowed then monetr throws it away.
  • It can only be used once. Once monetr claims it, it's spent.

That last one matters if something goes wrong. If the claim works but monetr fails to save the connection after that, the token is gone and you'll need to make a new one in your Bridge.

The new connection comes back with status pending.

Example

curl --request POST \
  --url "https://my.monetr.local/api/simplefin/link" \
  --user "$MONETR_API_KEY_ID:$MONETR_API_KEY_SECRET" \
  --header "Content-Type: application/json" \
  --data '{
    "name": "SimpleFIN Bridge",
    "setupToken": "aHR0cHM6Ly9icmlkZ2Uuc2ltcGxlZmluLm9yZy9zaW1wbGVmaW4vY2xhaW0vZXhhbXBsZQ=="
  }'
{
  "simpleFinLinkId": "sfx_01j7k3m9pw2rx8vt5nqdbe4chz",
  "name": "SimpleFIN Bridge",
  "apiUrl": "https://bridge.simplefin.org/simplefin",
  "status": "pending",
  "lastErrors": null,
  "lastManualSync": null,
  "lastSuccessfulUpdate": null,
  "lastAttemptedUpdate": null,
  "createdAt": "2024-07-19T14:22:38.905Z",
  "createdBy": "user_01fpwx3sdm7kb1s0jbrbvbdw4c",
  "updatedAt": "2024-07-19T14:22:38.905Z"
}

Errors

StatusWhen
400The setup token is missing, isn't a valid setup token, has already been used, or is for a server that isn't allowed. Also if the name is missing.
404SimpleFIN isn't enabled on this server.
500SimpleFIN couldn't be reached or the claim failed for some other reason, or monetr couldn't save the connection. If it's the last one, you'll need a new setup token.

POST Refresh available bank accounts

Asks your SimpleFIN Bridge what accounts it has and reconciles that against what monetr already knows. New accounts get added. Existing ones are left alone, and nothing is ever removed.

This only asks SimpleFIN for balances, not transactions. It still counts as one of the roughly 24 requests SimpleFIN lets you make each day though, so don't call it in a loop.

Whatever errors SimpleFIN sends back with the accounts get saved to the connection's lastErrors, replacing whatever was there before. A refresh never changes the connection's status, even when it fails.

In the app: Not used by the app yet.

POST /api/simplefin/link/:simpleFinLinkId/bank_accounts/refresh

Auth: API key, subscription required.

Path parameters

AttributeTypeRequiredDescription
simpleFinLinkIdstring (ulid)YesThe connection to refresh.

Returns 204 with no body. To see what it found, list the bank accounts afterwards.

Errors

StatusWhen
400simpleFinLinkId is malformed, SimpleFIN says your Bridge needs to be paid for, or SimpleFIN denied access. Denied usually means the token was revoked.
404No such connection, or SimpleFIN isn't enabled on this server.
500monetr couldn't reach SimpleFIN, or SimpleFIN failed for some other reason. The error from SimpleFIN is included.

SimpleFIN uses 402 when payment is required, but monetr sends that back as a 400 because monetr already uses 402 for its own billing.

GET List available bank accounts

Returns the accounts monetr found on a SimpleFIN connection, whether or not you've added them to your budget yet.

In the app: Not used by the app yet.

GET /api/simplefin/link/:simpleFinLinkId/bank_accounts

Auth: API key, subscription required.

Path parameters

AttributeTypeRequiredDescription
simpleFinLinkIdstring (ulid)YesThe connection whose accounts you want.

Example

curl --request GET \
  --url "https://my.monetr.local/api/simplefin/link/sfx_01j7k3m9pw2rx8vt5nqdbe4chz/bank_accounts" \
  --user "$MONETR_API_KEY_ID:$MONETR_API_KEY_SECRET"
[
  {
    "simpleFinBankAccountId": "sbac_01j7k4p2vx8we5rt9mnqbd3chf",
    "simpleFinLinkId": "sfx_01j7k3m9pw2rx8vt5nqdbe4chz",
    "simpleFinId": "ACT-0d5a1e7c-63b2-4f0e-9a8d-2c41f6b7e913",
    "connectionId": "CON-7b2e9f14-5c3a-4d81-b6e0-91a4c8d2f357",
    "name": "Everyday Checking",
    "institutionName": "Lakeside Credit Union",
    "currency": "USD",
    "status": "inactive",
    "currentBalance": 129544,
    "availableBalance": 127012,
    "createdAt": "2024-07-19T14:24:11.663Z",
    "createdBy": "user_01fpwx3sdm7kb1s0jbrbvbdw4c",
    "updatedAt": "2024-07-19T14:24:11.663Z"
  }
]

Errors

StatusWhen
400simpleFinLinkId is malformed.
404No such connection, or SimpleFIN isn't enabled on this server.