Guides

OAuth 2.0

Build apps that other inaiy workspaces install, with access limited to the scopes the admin approves.

Endpoints

GET /oauth/authorizeStart the authorization code flow (consent screen).
POST /oauth/tokenExchange a code, refresh token or client credentials for tokens (form-encoded).
POST /oauth/revokeRevoke an access or refresh token.
POST /oauth/introspectCheck whether a token is active and what it can do.
GET /oauth/userinfoClaims for the user who approved the app.

Full parameters are in the OAuth 2.0 reference.

Authorization code with PKCE

For apps acting on behalf of an inaiy user (web, single-page and mobile apps).

  1. Create a random code_verifier and its SHA-256 code_challenge.
  2. Send the user to /oauth/authorize with response_type=code, client_id, redirect_uri, scope, state, code_challenge and code_challenge_method=S256.
  3. The workspace admin approves the scopes.
  4. inaiy redirects back with a short-lived code and your state. Check that state matches.
  5. Exchange the code at /oauth/token with grant_type=authorization_code and the code_verifier.
Exchange the code
curl -X POST "https://api.inaiy.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=AUTH_CODE \
  -d redirect_uri=https://yourapp.com/callback \
  -d client_id=YOUR_CLIENT_ID \
  -d code_verifier=YOUR_CODE_VERIFIER
Token response
{
  "access_token": "wp_at_a1b2c3d4e5f6…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "contacts.read messages.write",
  "refresh_token": "wp_rt_z9y8x7w6v5…"
}

Refresh tokens

Access tokens last one hour. Call /oauth/token with grant_type=refresh_token to get a new pair, and store the new refresh token: refresh tokens rotate on every use.

Reuse detection

Using an old, already-rotated refresh token revokes the whole token family. If two servers refresh at the same time, one of them will be logged out — refresh in one place.

Client credentials

For server-to-server integrations with no user involved. Confidential clients call /oauth/token with grant_type=client_credentials, client_id and client_secret and get an access token (no refresh token) limited to the client's allowed scopes.

Scopes

ScopeGrants
contacts.readView contacts and their details.
contacts.writeCreate, update, and delete contacts.
conversations.readView conversations and their metadata.
conversations.writeUpdate, assign, and modify conversations.
messages.readView messages within conversations.
messages.writeSend messages on your behalf.
media.readView and download uploaded media files.
media.writeUpload media files for messages and template headers.
templates.readView approved message templates.
broadcasts.readView broadcast campaigns and their status.
broadcasts.writeCreate and manage broadcast campaigns.
catalog.writeCreate and update commerce catalog products via the Public API.
channels.readView connected WhatsApp, Instagram, and Messenger channels.
team.readView agents and teams in the workspace.
analytics.readView messaging, template, broadcast, inbox, commerce, drip, AI agent, Public API usage, and plan usage analytics.
webhooks.readReserved for the upcoming webhook management API; no Public API endpoint uses it yet.
webhooks.writeReserved for the upcoming webhook management API; no Public API endpoint uses it yet.

Ask for the fewest scopes your app needs; admins are more likely to approve a short list.