Machine-to-machine (M2M)
Machine-to-machine (M2M)
Scoped, short-lived credentials for server-to-server calls — no user, no static key
Machine-to-machine (M2M) is an OAuth 2.0 client_credentials grant: your own server holds a client_id and client_secret and calls the Brevo API as itself — there’s no end user to redirect and no consent screen. It’s the recommended way to authenticate server-to-server integrations going forward, in place of a static API key.
Why prefer M2M over a static API key
Use M2M for any new backend integration that calls Brevo as itself. Reach for a static API key only where you specifically need the simplicity of a single header with no token exchange step.
M2M is a different flow from OAuth apps (the authorization_code grant) — see Which flavor of OAuth do I need? if your app needs to act on behalf of a Brevo user instead of as itself.
Get started
Install the Brevo CLI
See Installation. If brevo app create’s app-type prompt doesn’t offer Machine to Machine, update to the latest version (see Upgrading).
Create an M2M app
Read the credentials back at any time with brevo app credentials --app-id <app-id> (add --reveal-secret to print the secret).
Pick every scope the app will ever need up front — you can widen or narrow the set later with brevo app scopes update, but each change is a full replace of the granted set. See the Scopes reference for the full catalog (the same scope names used by OAuth apps).
To script app creation non-interactively:
--m2m requires --scopes, and --m2m cannot combine with --redirect-uri, --ui-app/--ui-config, or --distribution public — an M2M app has no user to redirect and is private-distribution only.
Get an access token
Or request it directly, without the CLI:
Always request an explicit scope — omitting it currently returns a token scoped to every permission the app has, rather than failing closed. Pass the scopes you actually need, space-separated, e.g. --data-urlencode 'scope=contacts:read crm:read' (or brevo app token --app-id <id> --scope contacts:read,crm:read).
The token is a Bearer token, valid for ~1 hour. There’s no refresh token in the client_credentials grant — when it expires, request a new one the same way.
Manage the app over its lifetime
Every lifecycle command is keyed by --app-id.
See the CLI reference for every flag.
Limitations (v1)
- No access-token revocation. Deleting the app or rotating the secret stops new tokens from being issued, but a token already handed out stays valid until it expires (~1 hour). Store secrets in a secret manager and rotate promptly if one leaks.
- One account per credential. Multi-account M2M credentials aren’t supported yet.
- No refresh token. Request a new token with the same
client_credentialscall when the old one expires — this is standard for the grant, not a Brevo-specific gap.