Public app and OAuth: how other accounts connect your app

Last updated: 11 November 2026 · 8 min read

OAuth is the standard way an administrator of another company connects their Clomni account to your app without giving a password. On Clomni's consent screen the administrator reads what the app will do and presses “Allow”, and the app gets a separate token for that workspace. Clomni uses the OAuth 2.0 authorization code flow with PKCE (S256). A public app has no personal access tokens and no client_credentials.

Steps

  1. 1

    Preparation

    1. On developer.clomni.ai open “New app” and choose “Public app” as the kind. The kind cannot be changed later.
    2. Enter the redirect URIs (at most 10): the address Clomni sends the administrator back to after they give consent. The address must match character for character: scheme, host, port, path, query. No asterisk, # or user name.
    3. Only https is accepted. http://localhost, http://127.0.0.1 and http://[::1] are for local testing and work on any port, but only until the app is Live.
    4. Send the scopes for review. In a public app every scope goes through review.
    5. If you have a server, create a client secret. Without a secret the app counts as a public client and works with the client_id and PKCE only (for browser and mobile apps). Once a secret is created, the token request always needs it.
  2. 2

    Send the administrator to the authorize address

    The app makes a code_verifier (43-128 characters), computes code_challenge = BASE64URL(SHA256(code_verifier)) from it, makes a random state and keeps both in the session. Then it sends the administrator to this address:

    https://my.clomni.co/oauth/developer/authorize?client_id=capp_xxx&redirect_uri=https%3A%2F%2Fapp.example.com%2Fclomni%2Fcallback&response_type=code&scope=contacts:read%20conversations:read&state=STATE&code_challenge=CODE_CHALLENGE&code_challenge_method=S256

    All of these are required: client_id, redirect_uri, response_type=code, scope (scopes the app asked for that were not rejected), state (at most 500 characters), code_challenge (43 characters), code_challenge_method=S256. If the client_id is unknown or the redirect_uri does not match, Clomni does not redirect and shows the error on its own page. Other errors go back to the redirect URI as ?error=...&state=...: invalid_request, invalid_scope, unsupported_response_type, access_denied (the administrator declined).

  3. 3

    The administrator gives consent

    The consent screen shows “{name} wants to connect to Clomni”, “Developer: {company}”, the “Workspace” choice and the “The app will be able to” list. The administrator presses “Allow” or “Deny”. Only a workspace administrator can connect an app. The request works for 10 minutes and can be used once. What appears in the dashboard: the “Apps in the dashboard” article.

  4. 4

    Exchange the code for tokens

    Clomni returns: https://app.example.com/clomni/callback?code=...&state=.... First compare state with the one in the session. The code works for 60 seconds and only once. If it comes a second time, the tokens issued from the first exchange are revoked too.

    curl -X POST https://api.clomni.ai/v1/oauth/token \
      -u "$CLOMNI_CLIENT_ID:$CLOMNI_CLIENT_SECRET" \
      -d grant_type=authorization_code \
      -d code="$CODE" \
      -d redirect_uri="https://app.example.com/clomni/callback" \
      -d code_verifier="$CODE_VERIFIER"

    A public client sends client_id in the body instead of -u. The response has access_token (clomni_at_, 1 hour), refresh_token (clomni_rt_, 90 days), scope, workspace_id and installation_id. Store tokens by installation_id: one workspace is one installation.

  5. 5

    Refresh the token

    Send a request to the same address with grant_type=refresh_token and refresh_token=.... Every refresh returns a new refresh token: delete the old one. If an old refresh token comes a second time, Clomni treats it as theft and revokes the whole token family, and the administrator has to connect the app again. Do not refresh one installation from two processes at the same time. If you send scope, the token is narrowed, never widened.

  6. 6

    Working scopes and revoking

    The scopes that work on each request are the overlap of the scopes the administrator consented to and the scopes approved for the app right now. When a new scope is approved, it is not added to existing installations on its own: the administrator has to connect the app again. When an administrator removes the app in Settings › Workspace settings › Apps › “Connected apps”, all tokens stop at once and app.uninstalled goes to the app's webhook. If the person who connected the app is no longer an administrator, its tokens return 403 installation_owner_not_admin. You can revoke a token yourself with POST /v1/oauth/revoke.

  7. 7

    Testing before review, and the catalog

    Before review you can connect the app in its own workspace, as its owner, and try it on the test channel: scopes that are not approved work only there (the “Test channel” article). Once the listing is approved, the app appears in the catalog in the dashboard. The “Connect” button opens the app's install address (install_url), and your app starts the flow.

  8. 8

    Token errors

    • 400 invalid_grant: the code or refresh token is wrong, expired or already used, the redirect_uri or code_verifier does not match, or the installation was revoked.
    • 401 invalid_client: client_id or client_secret is wrong, or an app with a secret did not send it.
    • 400 unauthorized_client: the app is not public, or it is suspended or archived.
    • 400 invalid_scope, unsupported_grant_type.

Document