Mono Colombia

Authentication

How to authenticate Banking API requests with an API key or an OAuth 2.0 access token.

Every request to the Banking API must prove that it comes from your company. You can prove it with a long-lived API key, or with a short-lived access token that your server requests on its own. Mono accepts both on every Banking endpoint, so you can choose the one that fits your security practices.

A credential belongs to one service. Banking credentials work only on the Banking API, and a Core credential sent to a Banking endpoint is rejected.

Before you start

You will need:

  • Access to the Mono Dashboard for your organization.
  • An HTTPS client. Mono refuses requests that do not use TLS.
  • A safe place for secrets, such as a secrets manager. Never commit credentials to source control.

The conventions shared by every Mono product, such as the header format and environments, are in Authentication standards.

Choose a credential

API keyOAuth 2.0 access token
How long it lastsUntil you revoke it30 minutes, then you request a new one
What it can doWhat its roles allowWhat its scopes allow
How you get itCreated in the Mono DashboardRequested by your server with a client ID and secret
Where it goesAuthorization: Bearer <key>Authorization: Bearer <access_token>

A role is a named set of permissions, such as "Admin" or "Viewer", attached to an API key. A scope is a single permission, such as transfers:readonly, attached to an access token. Mono maps each role permission to the scopes that grant the same action, so an endpoint accepts either credential for the same operation.

Option 1: API keys

An API key is a secret string that stays valid until you revoke it. To create or revoke keys, sign in to the Mono Dashboard and open the API key management section.

When you create a key, choose its roles. The key can do exactly what those roles allow. For example, a key with the "Viewer" role can read data but not move money.

Send the key in the Authorization header of every request:

curl https://api.cuentamono.com/v1/accounts \
  -H "Authorization: Bearer $MONO_API_KEY"

Keys do not expire, so rotating them is your responsibility: create a new key, deploy it, then revoke the old one.

Option 2: OAuth 2.0 access tokens

OAuth 2.0 is an industry standard for issuing temporary credentials. Mono uses its client credentials flow, designed for server-to-server integrations. Your server exchanges a permanent client ID and client secret for an access token that lasts 30 minutes. Think of it as trading an employee badge for a day pass: the pass expires, the badge stays in the safe.

Get a credential

Banking OAuth credentials are not self-service yet: the Mono Dashboard cannot create them for Banking organizations. To get one, contact your Mono account team and tell them which scopes your integration needs.

Mono gives you a client ID and a client secret. Store both in your secrets manager as soon as you receive them. To change the scopes later, or to disable or delete the credential, contact the same team.

Request an access token

Call the token endpoint with grant_type=client_credentials, your client ID and secret, and the scopes you need, separated by spaces:

curl https://api.cuentamono.com/v1/oauth/token \
  -d grant_type=client_credentials \
  -d client_id="$MONO_CLIENT_ID" \
  -d client_secret="$MONO_CLIENT_SECRET" \
  -d scope="accounts:readonly transfers"

The endpoint accepts application/x-www-form-urlencoded, as above, or the same fields as JSON. In sandbox, use https://api.sandbox.cuentamono.com.

{
  "access_token": "<access_token>",
  "token_type": "Bearer",
  "expires_in": 1800,
  "refresh_token": "<refresh_token>",
  "scope": "accounts:readonly transfers"
}

Always send scope. If you leave it out, Mono still issues a token, but with no scopes, and every endpoint then answers 403. If you ask for a scope your credential does not have, the whole request fails with 400 invalid_scope; Mono never returns a token with only part of what you asked for.

Call the API

Send the access token in the Authorization header, exactly like an API key:

curl https://api.cuentamono.com/v1/accounts \
  -H "Authorization: Bearer $MONO_ACCESS_TOKEN"

Renew the token

expires_in is the token's remaining lifetime in seconds: 1800 when it is issued. Request a new token before it runs out. You have two ways:

  • Request a new token with your client credentials, exactly as above. This is the simplest option for a server that always holds its secret.
  • Use the refresh token. The response also carries a refresh_token, valid for one day. Exchange it for a new access token:
curl https://api.cuentamono.com/v1/oauth/token \
  -d grant_type=refresh_token \
  -d client_id="$MONO_CLIENT_ID" \
  -d client_secret="$MONO_CLIENT_SECRET" \
  -d refresh_token="$MONO_REFRESH_TOKEN"

Each refresh returns a new refresh token. Use the new one next time and discard the old one.

Check or revoke a token

Two more endpoints take your client ID and secret plus the token itself:

  • Introspect (grant_type=introspect) tells you whether a token is still active, when it expires, and which scopes it carries. An expired or unknown token returns {"active": false}.
  • Revoke (grant_type=revoke) invalidates an access token or a refresh token at once. It answers 200 even if the token had already expired.

Revoke tokens you no longer need, for example when you retire a server. The endpoint contracts are in the Banking authentication reference.

Scopes

Request the narrowest scopes your integration needs. Two rules apply across the catalog:

  • A bare scope, such as transfers, grants every action on that resource, including the specific actions listed below it.
  • A :readonly scope grants reads only. It does not include the specific actions: cards:readonly does not grant cards:details.
ScopeGrants
accountsAll permissions for accounts
accounts:readonlyRead accounts
accounts:balancesRead the balance of an account
transfersAll permissions for bank transfers, and reading the bank catalog
transfers:readonlyRead bank transfers and the bank catalog
transfers:prepareCreate bank transfers that wait for approval
collection_linksAll permissions for collection links and collection intents, and reading the bank catalog
collection_links:readonlyRead collection links, collection intents, and the bank catalog
cardsAll permissions for cards
cards:readonlyRead cards
cards:detailsRead a card's sensitive details: number, security code, expiry
spending_controlsAll permissions for card spending controls
spending_controls:readonlyRead card spending controls

Failures

The token, introspect, and revoke endpoints answer errors in the OAuth format, with error and error_description fields. For example, 400 invalid_scope means you asked for a scope your credential does not have.

Every other endpoint answers with the standard error envelope:

StatusCodeWhat happened
401expired_tokenThe token expired, was revoked, or belongs to another service, such as Core.
403not_authorizedThe credential is valid, but its scopes or roles do not allow this endpoint.

A Core token sent to a Banking endpoint gets the same 401 expired_token as an expired token. If a fresh token is rejected that way, check that it came from /v1/oauth/token, not from /v1/core/oauth/token.

Next steps

On this page