API
Language
Ask for a seat

Closed beta. Nothing here is callable yet. These docs describe the day-one contract, and names marked proposed may change before the beta opens. Ask for a seat

Docs · Getting started

Quickstart

Two calls to your first balance: exchange your client credentials for a token, then read your accounts.

1. Create a client in the Novo app

The account owner creates an API client in the Novo app, after a verification step, and picks its scopes. For this guide, accounts:read is enough. The app shows the client secret once: store it like a password.

2. Exchange the credentials for a token

Send the client id and secret with HTTP Basic to the token endpoint. The response is an opaque bearer token that expires after expires_in seconds (900, so 15 minutes) proposed. Reuse it until it expires rather than asking for a new one on every call.

Request
curl -X POST "https://$NOVO_API_HOST/v1/oauth/token" \
  -u "nvo_client_example:$CLIENT_SECRET" \
  -d "grant_type=client_credentials"
Response
{
  "access_token": "nvo_at_example_opaque_token",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "accounts:read transactions:read"
}

3. Read your accounts

Send the token as Authorization: Bearer. Account and routing numbers come back masked to the last 4 digits, and balances are decimal strings.

Request
curl "https://$NOVO_API_HOST/v1/accounts" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
  "data": [
    {
      "id": "acct_example_01",
      "name": "xxxxxx1234",
      "type": "EXAMPLE_TYPE",
      "status": "EXAMPLE_STATUS",
      "account_number_last4": "1234",
      "routing_number_last4": "5678",
      "balance": {
        "available": {
          "amount": "1250.00",
          "currency": "USD"
        },
        "current": {
          "amount": "1300.00",
          "currency": "USD"
        },
        "spendable": {
          "amount": "1150.00",
          "currency": "USD"
        }
      },
      "opened_at": "2024-03-14"
    }
  ]
}

The same in TypeScript

TypeScript
const host = process.env.NOVO_API_HOST;
const basic = Buffer.from(`nvo_client_example:${process.env.CLIENT_SECRET}`).toString("base64");

// 1. Exchange the client credentials for a short-lived token.
const token = await fetch(`https://${host}/v1/oauth/token`, {
  method: "POST",
  headers: {
    Authorization: `Basic ${basic}`,
    "Content-Type": "application/x-www-form-urlencoded",
  },
  body: "grant_type=client_credentials",
}).then((r) => r.json());

// 2. Read the accounts with it.
const accounts = await fetch(`https://${host}/v1/accounts`, {
  headers: { Authorization: `Bearer ${token.access_token}` },
}).then((r) => r.json());

console.log(accounts.data[0].balance.available);
// { amount: "1250.00", currency: "USD" }

Next

Page through transactions with a cursor, learn the conventions, and read how to handle errors and retries. If an agent makes the calls, give it the short-lived access token and keep the client secret in your secret store, where only your token exchange uses it.