Docs · Getting started
Authentication
The API uses the OAuth 2.0 client credentials grant. The account owner creates a client in the Novo app; your code exchanges it for a short-lived token and sends that token on every call.
Clients
Scopes
The owner picks a client’s scopes when creating it. They’re fixed for the life of the client: to change them, create a new client. Anything a scope doesn’t grant is refused.
accounts:read- Balances and account details, numbers masked to the last 4 digits
transactions:read- Posted, pending and card transactions
bookkeeping:read- Bookkeeping transactions
cards:read- Card list with the last 4 digits and status
cards:freeze- Freeze a card. Freeze only: unfreezing stays in the Novo app
Access tokens
Exchange the client id and secret at /v1/oauth/token with grant_type=client_credentials. HTTP Basic is the default; sending both as form fields also works.
curl -X POST "https://$NOVO_API_HOST/v1/oauth/token" \
-u "nvo_client_example:$CLIENT_SECRET" \
-d "grant_type=client_credentials"The token endpoint answers with OAuth 2.0 errors rather than problem details: one of invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope. Any problem with the client itself gets the same invalid_client answer, whatever the cause.
Revocation
The owner can revoke a client in the Novo app at any time. Revocation takes effect within 30 seconds proposed, plus any call already in flight. A revoked or suspended client, or one Novo has switched off, gets 401 client-disabled.
If the owner this client is bound to loses the owner role, or their profile is locked or no longer in good standing, calls stop. You get 403 owner-standing-lost first; once the client is revoked, 401 client-disabled. A current owner creates a new client in the app.
Giving access to an AI agent
Keep the client secret in your secret store and use it only to call the token endpoint. The agent gets the short-lived access token, never the secret: a leaked token is at most 15 minutes of the client’s scopes, while a leaked secret is the whole client until you rotate it proposed. Give the agent a client with only the scopes it needs: a client without cards:freeze can only read. See untrusted text for what an agent should never take as an instruction.
Locking a key to where it runs Planned
You can lock a key to the tools and machines you’ve approved. If it’s used from anywhere else, it stops and waits for your yes in the Novo app.
Your integration holds a key pair where it runs and signs each request with it (OAuth 2.0 DPoP, RFC 9449). Novo never sees the private key; your tool sends only the public key. Once a key is locked, a stolen client secret or access token gets nothing on its own. A locked client gets token_type DPoP instead of Bearer, and sends a fresh proof with every request.
What it doesn’t stop: