Introduction
The Teller API is organized around REST. Resources have predictable, self-describing URLs and contain links to related resources. Our API accepts form-encoded requests and returns JSON encoded responses. It uses standard HTTP status codes, authentication, and methods in their usual ways.
You can use the Teller API in sandbox mode, which is free, does not call out to any real banks, and does not affect your live data. The access token you use determines whether your request is handled in the live or sandbox enviroments.
Access tokens for the live environment are obtained using Teller Connect when a user successfully connects a bank account to your Teller application.
Take a look at the Teller Connect integration guide to learn how to integrate Teller Connect into your application.
https://api.teller.io/
test_DABfg5yAd-6ByjlMifyHMQ
Authentication
The Teller API uses TLS client certificates to authenticate your API requests. Secondly it uses access tokens to identify the user whose bank accounts your API call operates on. Access tokens are tied to your application, they are useless without your client certificate and its private key.
Client certificates are necessary for live production API calls. In the interests of getting up and running as quickly as possible they're not required in the sandbox environment. We recommend using client certificates as soon as possible in order to become familiarised with them.
It's of paramount importance that you keep your private key confidential, anyone that knows it is able to make API requests as you. If you suspect your private key has been compromised, immediately revoke it and request a new certificate from the certificate dashboard. Your new certificate will have a new private key.
Access tokens are encoded using HTTP Basic Auth. The access token is given as the username value, the password field should be left empty and is ignored by the API server. Teller uses access tokens to identify the resource owner and determine that your application has their consent to operate on their resources, i.e. their bank accounts.
http https://api.teller.io/accounts --auth test_DABfg5yAd-6ByjlMifyHMQ:
Errors
Teller uses standard HTTP response status codes to indicate the success or failure of a
request. Status codes in the 2xx
denote a successful request. Status codes in the
4xx
range denote a client error, e.g. not using a client certificate to make the request, a
problem with the user access token, etc. Status codes in the 5xx
range denote a problem on
our end, e.g. a bank is unavailable and it's not possible or otherwise doesn't make sense to gracefully
handle the exception.
-
error
- object
- An object describing the error condition.
-
error.code
- string
- The error condition.
-
error.message
- string
- A human readable string describing the error and how to resolve it.
OK | A successful request. |
---|---|
Accepted | A payment instruction was accepted by the financial institution for processing. |
Bad Request | The request was unacceptable. This status is used when a request that must be made with a Teller client certificate is made without one. |
Unauthorized | A request was made without an access token where one was required. |
Forbidden | A request was made with an invalid or revoked access token. |
Unprocessable Entity | A request was made with an invalid request body. |
Bad Gateway | A 500 level response was received when making a request to a financial institution where a graceful fallback is not possible, e.g. a payment instruction. |
Versioning
Teller uses dated versions with the latest one being 2020-10-12. By default all API requests will use the version specified in the Teller Dashboard.
In order to test a new version, you can request it using the Teller-Version
HTTP header.
Once you are ready to upgrade to a new version permanently, you can do so from the dashboard.
You will have 72 hours to rollback to the version you were previously using.
http https://api.teller.io/accounts Teller-Version: 2019-07-01
Enrollment status
Teller lets you know about the current status of an enrollment by returning the
teller-enrollment-status
header for several endpoints.
When an enrollment gets disconnected, Teller can also
send you a webhook event of type enrollment.disconnected
.
-
healthy
- When the enrollment is connected to the institution.
-
disconnected
-
When the enrollment is disconnected from the institution the user should reconnect with Teller Connect.
Note: In the future we may provide the reason for disconnection by returning a hierarchical status, e.g.disconnected.mfa
ordisconnected.institution.outage
. We recommend parsing the status as a dot-separated string where the first token isdisconnected
.
- teller-enrollment-status: healthy
- teller-enrollment-status: disconnected
- GET /accounts/:id
- GET /accounts/:id/details
- GET /accounts/:id/balances
- GET /accounts/:account_id/transactions
- GET /accounts/:account_id/transactions/:id
Accounts
The Accounts resource represents a collection of the user's bank accounts.
-
currency_code
- string
- The ISO 4217 currency code of the account.
-
enrollment_id
- string
- The id of the enrollment that the account belongs to.
-
id
- string
- The id of the account itself.
-
institution
- object
- An object containing information about the bank that holds the account
-
institution.id
- string
- The
snake_cased
name of the bank that holds the account. -
institution.name
- string
- The
Title Cased
name of the bank that holds the account. -
last_four
- string
- The last four digits of the account number.
-
links
- object
- An object containing links to related objects.
-
links.self
- string
- A
self
link to the account. -
links.details
- string
- A link to the account's details, such as account number and routing numbers.
-
links.balances
- string
- A link to the account's balances.
-
links.transactions
- string
- A link to the account's ledger transactions.
-
name
- string
- The account's name.
-
type
- string
- The account's type e.g depository.
-
subtype
- string
- The account's subtype e.g checking or savings.
- GET /accounts
- GET /accounts/:id
{
"currency_code": "USD",
"enrollment_id": "test_enr_OmGfFxUJ",
"id": "test_acc_sHzjaj3J",
"institution": {
"id": "brex",
"name": "Brex"
},
"last_four": "4459",
"links": {
"balances": "https://api.teller.io/accounts/test_acc_sHzjaj3J/balances",
"details": "https://api.teller.io/accounts/test_acc_sHzjaj3J/details",
"self": "https://api.teller.io/accounts/test_acc_sHzjaj3J",
"transactions": "https://api.teller.io/accounts/test_acc_sHzjaj3J/transactions"
},
"name": "Teller API Sandbox Checking",
"subtype": "checking",
"type": "depository"
}
Account Details
The Account Details resource exposes the account's ACH routing number, if different, its wire routing number and its account number.
-
account_id
- string
- The id of the account the balance belongs to.
-
account_number
- string
- The account's account number.
-
links
- object
- An object containing links to related objects.
-
links.self
- string
- A
self
link to the account. -
links.account
- string
- A link to the account that the details belongs to.
-
routing_numbers
- object
- An object containing the account's routing numbers.
-
routing_numbers.ach
- string
- The account's ACH routing number.
-
routing_numbers.wire
- string
- The account's wire routing number.
- GET /accounts/:id/details
{
"account_id": "test_acc_sHzjaj3J",
"account_number": "4040614459",
"links": {
"account": "https://api.teller.io/accounts/test_acc_sHzjaj3J",
"self": "https://api.teller.io/accounts/test_acc_sHzjaj3J/details"
},
"routing_numbers": {
"ach": "561360954"
}
}
Account Balances
The Account Balances resource represents the account's real-time balances.
-
account_id
- string
- The id of the account the balances belong to.
-
ledger
- string
- The account's ledger balance. The ledger balance is the total amount of funds in the account.
-
available
- string
- The account's available balance. The available balance is the ledger balance less any outstanding holds or debits that have not yet posted to the account.
-
links.self
- string
- A
self
link to the account. -
links.account
- string
- A link to the account that the balances belongs to.
- GET /accounts/:id/balances
{
"account_id": "test_acc_sHzjaj3J",
"available": "75.82",
"ledger": "75.82",
"links": {
"account": "https://api.teller.io/accounts/test_acc_sHzjaj3J",
"self": "https://api.teller.io/accounts/test_acc_sHzjaj3J/balances"
}
}
Transactions
The Transactions resource represents the known transactions on the account. Each individual Transaction resource exposes an individual transaction on the account either posted or pending.
-
account_id
- string
- The id of the account that the transaction belongs to.
-
amount
- string
- The signed amount of the transaction as a string.
-
date
- string
- The ISO 8601 date of the transaction.
-
description
- string
- The unstructured transaction description as it appears on the bank statement.
-
status
- string
- The transaction's status, e.g
posted
orpending
. -
id
- string
- The id of the transaction itself.
-
links
- object
- An object containing links to related objects.
-
links.self
- string
- A
self
link to the account. -
links.account
- string
- A link to the account that the transaction belongs to.
-
running_balance
- optional string
- The running balance of the account that the transaction belongs to. Running balance is only present on transactions with a posted status.
-
type
- string
- The type code transaction, e.g.
card_payment
.
Pagination
The Transactions endpoint returns all transactions for the given account. Usually this does not represent a large amount of data transfer, but if your application has specific requirements of minimising the amount of data going over the wire the transactions list endpoint supports pagination controls.
Pagination controls are given as query params on the request URL.
GET /accounts/:account_id/transactions?count=5&from_id=txn_test
-
count
- integer
- The maximum number of transactions to return in the API response.
-
from_id
- string
- The transaction from where to start the page. The first transaction in the API response will be the one immediately before the transaction in the ledger with this id.
- GET /accounts/:account_id/transactions
- GET /accounts/:account_id/transactions/:id
{
"account_id": "test_acc_sHzjaj3J",
"amount": "-4.94",
"date": "2020-10-12",
"description": "Nordstrom",
"id": "test_txn_qlbhxMBS",
"links": {
"account": "https://api.teller.io/accounts/test_acc_sHzjaj3J",
"self": "https://api.teller.io/accounts/test_acc_sHzjaj3J/transactions/test_txn_qlbhxMBS"
},
"running_balance": "75.82",
"status": "posted",
"type": "card_payment"
}
Webhooks
Teller can send you webhook events related to your application and its accounts,
e.g. when an enrollment gets diconnected and the user should reconnect using
Teller Connect, Teller will send you a webhook event of type
enrollment.disconnected
and your application can take appropriate action.
How to listen to webhook events
To start listening, go to the Teller dashboard, and configure your Webhook URL.
Teller sends a webhook event by making a POST
request to your
configured URL with JSON encoded attributes. Your application should respond
with a 2xx
status code. If Teller doesn't receive a 2xx
status code it will retry sending the webhook event with exponential backoff.
As a best practice, your application shouldn't perform any heavy operations
before responding with a 2xx
in order to avoid a timeout and a retry.
id
- string
- The id of the webhook event.
payload
- object
- Event type specific data.
timestamp
- string
- The ISO 8601 timestamp of the event.
type
- string
- The type of the event, e.g
enrollment.disconnected
.
How to test a webhook
Go to the
Teller dashboard,
and press the Test button next to your Webhook URL. When you press it,
Teller will send you a test webhook event of type webhook.test
,
and display a message about its delivery status.
How to verify that events were created by Teller
Teller signs every webhook event with all non-expired signing secrets, that only you and Teller know. You can get your signing secrets from the Teller dashboard.
Teller sends a signature in the Teller-Signature
HTTP header:
Teller-Signature: t=signature_timestamp,v1=signature_1,v1=signature_2,v1=...
Most of the time there will be only one non-expired signing secret, so the signature header will look like this:
Teller-Signature: t=signature_timestamp,v1=signature
To verify that the payload was created by Teller, you have to calculate the signature and it must be equal to the signature extracted from the signature header.
To calculate the signature:
-
Create
signed_message
by joiningsignature_timestamp
and the request's JSON body with a.
character -
Compute HMAC with SHA-256 using the non-expired signing secret as the key and
signed_message
as the message
To prevent replay attacks you should reject webhook events with a
signature_timestamp
(Unix time) older than 3 minutes.
How to expire a signing secret
When you have a policy to periodically roll secrets, Teller allows you to do it without a gap in signature verification.
To expire the current signing secret, go to the Teller dashboard and select when the secret should expire, e.g. in 2 hours. When you press Save, Teller will create a new non-expired secret, and from that moment, Teller will sign all webhook events with both secrets until the old secret expires:
Teller-Signature: t=signature_timestamp,v1=signature_with_new_secret,v1=signature_with_old_secret
This gives you time to update your verification code with the new secret.
Event types
enrollment.disconnected
Sent when an enrollment gets disconnected and the user should reconnect using Teller Connect.
payload.enrollment_id
- string
- The id of the enrollment.
{
"id": "wh_ng2gggp9diogcn9op0000",
"payload": {
"enrollment_id": "enr_ng2gggp9diogcn9op0001"
},
"timestamp": "2021-03-07T00:22:38Z",
"type": "enrollment.disconnected"
}