message.comDevelopers

OAuth apps Planned

Build your own app on the message.com platform. Register an OAuth client, request the scopes you need, exchange auth codes for access and refresh tokens. The foundation for the public app marketplace and for any third-party integration that needs per-workspace consent.

This is the public-developer programme. If you are building an integration for your own workspace only, an API key is simpler. OAuth apps are for distribution.

Register an OAuth client

From your workspace, open Settings → Developers → OAuth apps → Create app. Provide a name, logo, homepage URL, and at least one redirect URI. We issue a client_id and a client_secret; store the secret in your backend.

Apps start in development mode, usable only by your workspace. To list publicly, submit for review with the standard OAuth-app review checklist (security, privacy policy, branding).

Authorization code flow

We implement the standard OAuth 2.0 authorization code flow with PKCE (Proof Key for Code Exchange) recommended for all clients. Public clients (no client secret) must use PKCE. See RFC 6749 for the underlying spec.

Step 1: redirect the user

Authorize URL
# Redirect the user to:
https://app.message.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https%3A%2F%2Fyour-app.com%2Fcallback&
  scope=conversations%3Aread+messages%3Asend&
  state=opaque-csrf-token

Step 2: handle the callback

After the user consents, we redirect back to your redirect_uri with a code and the state you sent. Verify state matches what you stored.

Step 3: exchange the code for a token

Token exchange
# Exchange the code for a token
curl -X POST 'https://app.message.com/oauth/token' \
  -d 'grant_type=authorization_code' \
  -d 'code=AUTHORIZATION_CODE' \
  -d 'redirect_uri=https://your-app.com/callback' \
  -d 'client_id=YOUR_CLIENT_ID' \
  -d 'client_secret=YOUR_CLIENT_SECRET'

# Response
{
  "access_token": "msg_oauth_abc...",
  "refresh_token": "msg_refresh_xyz...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "conversations:read messages:send",
  "workspaceId": "uuid"
}

Step 4: refresh when expired

Access tokens last one hour. Refresh tokens last 90 days from last use. Use the refresh token to get a new access token without prompting the user.

Refresh
# Refresh when the access token expires
curl -X POST 'https://app.message.com/oauth/token' \
  -d 'grant_type=refresh_token' \
  -d 'refresh_token=YOUR_REFRESH_TOKEN' \
  -d 'client_id=YOUR_CLIENT_ID' \
  -d 'client_secret=YOUR_CLIENT_SECRET'

Available scopes

Request the minimum scopes you need. Users see the requested scopes during consent; broader scopes lower install rates. Scopes are namespaced as resource:action.

  • conversations:read, conversations:write
  • messages:send, messages:read
  • visitors:read, visitors:write
  • agents:read
  • webhooks:write (subscribe to outgoing webhooks)
  • reports:read
  • ai:read, ai:invoke

Webhooks for OAuth apps

OAuth apps can subscribe to workspace events. We sign every delivery with HMAC-SHA256 using your client secret. Replay protection is enforced by timestamp window (5 minutes). See signature verification for the canonical pattern.

Rate limits

OAuth apps share the workspace's rate-limit budget by default. Apps that need higher limits can request an elevated tier during review. Per-app rate-limit headers are returned on every response.

The marketplace

Approved OAuth apps can be listed in the message.com app marketplace, surfacing them to workspaces as a one-click install. Submission requires a security review, a privacy policy, support contact, and demo footage. We do not charge a marketplace fee on the platform tier; revenue-share applies only to apps that monetise through our billing.

Common pitfalls

  • Never embed the client secret in a browser bundle. Public clients use PKCE and have no secret.
  • Always verify state. Without it, your callback is vulnerable to cross-site request forgery.
  • Do not request *:write scopes you do not use. Users notice.
  • Refresh tokens rotate on use; store the new one returned from each exchange. Reusing an old refresh token returns 401 and forces re-consent.