> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.brevo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.brevo.com/_mcp/server.

# Private and public apps

Every Brevo app has a **distribution type**: `private` or `public`. It decides who can authorize your app, and it's set once, when you create the app.

* A **private app** is for your own organization: internal tools, automations, and integrations you build for your own team. It works as soon as you create it.
* A **public app** is for every Brevo user: for example, a SaaS product that offers a Brevo integration to its own customers. It goes through a review by Brevo, and once approved, any Brevo account can authorize it.

> **Note**
>
> Public apps require **Brevo CLI 2.5.0 or later**. Run `brevo --version` to check, and see [Upgrading](/docs/cli-reference#upgrading) to update.

## Private vs public at a glance

|                                   | Private app                                                                                                                                                      | Public app                                                                                                                                      |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Who can authorize it**          | Users in your own Brevo organization                                                                                                                             | Any Brevo account, once approved                                                                                                                |
| **Review by Brevo**               | None, usable right away                                                                                                                                          | Required before it's available to other accounts                                                                                                |
| **How users find it**             | You share it within your organization                                                                                                                            | You distribute it: an install link in your product, or a listing on third-party marketplaces. Public apps aren't listed on a Brevo marketplace. |
| **App types**                     | OAuth (consent-based or [machine-to-machine](/docs/oauth-m2m-authentication)), [UI apps](/docs/apps-action-links), [Brevo Functions](/docs/apps-brevo-functions) | Consent-based OAuth apps only (UI apps can't be public for now)                                                                                 |
| **OAuth client**                  | Confidential client with a client secret                                                                                                                         | Authorization code with PKCE, no client secret                                                                                                  |
| **Brevo Developer Terms**         | No agreement step                                                                                                                                                | You agree to them when you create the app, and confirm them again when you submit it                                                            |
| **Change the distribution later** | Not possible                                                                                                                                                     | Not possible                                                                                                                                    |

> **Warning**
>
> **The distribution type is fixed at creation.** `brevo app upload` refuses a changed `distribution_type`. To move an integration from private to public, create a new public app.

### Which one should you choose?

* Choose **private** if only your own organization will use the app, if your backend calls the API as itself (M2M), or if you're building a Brevo Function or a UI app (UI apps can't be public for now).
* Choose **public** if users outside your organization will connect their own Brevo accounts to your product.

## Create a public app

### Create the app with public distribution

```bash
brevo app create --distribution public
```

Or run `brevo app create` and choose **Public** when asked "What distribution type should this app use?". Non-interactive runs (`--json` or piped input) default to `private`, so pass `--distribution public` explicitly.

### Agree to the Brevo Developer Terms

Right after you choose Public, the CLI opens the [Brevo Developer Terms](/docs/apps-developer-terms) in your browser and asks:

```txt
? Do you confirm that you have read and agree to the Brevo Developer Terms? (y/N)
```

Answering no cancels the creation; nothing is sent to Brevo. In scripts and CI, where no question can be asked, add `--accept-developer-terms` to confirm agreement explicitly:

```bash
brevo app create --name "My App" --distribution public \
  --redirect-uri https://myapp.com/callback \
  --accept-developer-terms --json
```

### Choose OAuth app and add your OAuth callback URLs

When asked "What type of app are you building?", choose **OAuth app**. UI apps can't be public for now. A public app is always a consent-based OAuth app, so the CLI doesn't ask which OAuth flow to use. Add at least one OAuth callback URL (`http://` or `https://`): the URL users are sent back to after they authorize your app. Use your production callback URL here, or add it later in `auth.redirect_uris` in `app-config.json` and run `brevo app upload`.

### Build the OAuth flow with PKCE

A public app has no client secret. It uses the authorization code flow with [PKCE](https://datatracker.ietf.org/doc/html/rfc7636) (`S256`): your server creates a random `code_verifier` for each authorization, sends its SHA-256 hash as `code_challenge` on the authorize request, and presents the verifier on the token exchange instead of a `client_secret`.

The test server from [`brevo app scaffold`](/docs/cli-reference#brevo-app-scaffold) already does this for a public app. See [Distribute your app with an install link](#distribute-your-app-with-an-install-link) below for the exact requests.

## Submit your app for review

Before you submit, your app needs to be complete on Brevo's side:

* **Upload it at least once.** Run `brevo app upload` so Brevo has a version to review.
* **Fill in the required fields.** For example, set `logo_uri` in `app-config.json` to your logo URL, then run `brevo app upload`. If a field is missing, `brevo app submit` lists it by the name the Brevo API uses (for example `logoLink`), which can differ from the `app-config.json` key.
* **Keep `app-config.json` in sync.** If your local file differs from the app on Brevo (name, redirect URLs, scopes, logo or version), `brevo app submit` stops and shows the difference. Run `brevo app upload` to push your local changes, then submit again.

Then run:

```bash
brevo app submit
```

The CLI shows the app configuration being submitted and asks you to confirm this statement:

> I have read and agree to the Brevo Developer Terms. I confirm that the information in this submission is accurate and complete, and that my app complies with the Brevo Developer Terms and all applicable laws. I understand that Brevo's activation of my app does not constitute a review, certification, or endorsement of my app.

Once you confirm, the CLI opens a submission form in your browser. **Your app is submitted only when you complete and send that form.**

In scripts, `--json` prints the form URL instead of opening a browser, and `--accept-submission-terms` confirms the statement:

```bash
brevo app submit --app-id <app-id> --json --accept-submission-terms
```

```json
{ "app_id": "<app-id>", "form_url": "https://…" }
```

## Track the review

Brevo emails you the decision, generally within 7 days. You can check where your app stands at any time:

```bash
brevo app status
```

| Status              | Meaning                                                                                          |
| ------------------- | ------------------------------------------------------------------------------------------------ |
| `draft`             | Set up, but not submitted for review yet                                                         |
| `submitted`         | Submitted and waiting to be reviewed                                                             |
| `in_review`         | Being reviewed by Brevo                                                                          |
| `approved`          | Approved: any Brevo account can now authorize your app                                           |
| `rejected`          | Not approved. Check your email for the details.                                                  |
| `changes_requested` | Changes were requested. Check your email for the details.                                        |
| `unknown`           | No status is available yet. Check that the app is public and that you've run `brevo app upload`. |

Reviewer feedback is sent by email only; `brevo app status` shows the status, not the feedback. Add `--json` to get `{ "state": "…", "message": "…" }`.

## Distribute your app with an install link

Brevo doesn't list public apps on a Brevo marketplace. Once your app is approved, you decide where users find it, for example inside your own product or on third-party marketplaces.

Your **install link** is a URL on your own server, for example `https://yourapp.com/connect/brevo`. The CLI doesn't generate one for you. Because of PKCE, the Brevo authorize URL is different for every authorization, so your server builds it each time someone opens your install link. If you're a SaaS product building an integration with Brevo, you can add the install link inside your product, for example as a **Connect Brevo** button. You can also use the same link in a third-party marketplace listing.

### Redirect the user to Brevo

Get your app's `client_id` from the `brevo app create` output or with [`brevo app credentials`](/docs/cli-reference#brevo-app-credentials). A public app has no client secret.

When someone opens your install link, your server creates a `state` value and a `code_verifier`, keeps both server-side, and redirects the user to:

```txt
https://oauth.brevo.com/realms/partner/oauth/authorize
  ?response_type=code
  &client_id=<CLIENT_ID>
  &redirect_uri=<REDIRECT_URI>
  &state=<STATE>
  &scope=<SPACE_SEPARATED_SCOPES>
  &code_challenge=<BASE64URL_SHA256_OF_CODE_VERIFIER>
  &code_challenge_method=S256
```

The user signs in to their Brevo account and approves the scopes your app requests.

### Exchange the code for tokens

Brevo redirects back to your `redirect_uri` with a `code` and the `state`. Check that `state` matches, then exchange the code. Send the `code_verifier`, not a client secret:

```bash
curl --request POST \
  --url https://oauth.brevo.com/realms/partner/oauth/token \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'client_id=<CLIENT_ID>' \
  --data-urlencode 'code_verifier=<CODE_VERIFIER>' \
  --data-urlencode 'code=<CODE>' \
  --data-urlencode 'redirect_uri=<REDIRECT_URI>'
```

Store the user's tokens, then call the API with `Authorization: Bearer <access_token>`. To refresh, send `grant_type=refresh_token`, `client_id` and `refresh_token` to the same token endpoint, with no `client_secret`. The [OAuth integration guide](/docs/oauth-integration-guide) covers the token response and errors.

## Update an approved app

**Changing an approved app's scopes requires a new review.** Edit `auth.scopes` in `app-config.json`, run `brevo app upload`, then run `brevo app submit` and wait for Brevo's email.

## Withdraw an app

```bash
brevo app withdraw
```

Withdrawing takes your app out of submission. If your app was approved, the approved version is no longer available to Brevo accounts. To make it available again, run `brevo app submit` and go through the review again.

The command asks for confirmation; add `--force` to skip it in scripts. If the app was never submitted, it tells you so and changes nothing.

## Related

#### [Create your first app](/docs/apps-getting-started)

Install the CLI and create an app.

#### [CLI reference](/docs/cli-reference)

Every command and flag, including `submit`, `status` and `withdraw`.

#### [OAuth integration guide](/docs/oauth-integration-guide)

The authorization code flow, tokens and refresh.

#### [Brevo Developer Terms](/docs/apps-developer-terms)

The terms that apply to public apps.