Guides
OAuth 2.0
Build apps that other inaiy workspaces install, with access limited to the scopes the admin approves.
Endpoints
GET /oauth/authorize | Start the authorization code flow (consent screen). |
POST /oauth/token | Exchange a code, refresh token or client credentials for tokens (form-encoded). |
POST /oauth/revoke | Revoke an access or refresh token. |
POST /oauth/introspect | Check whether a token is active and what it can do. |
GET /oauth/userinfo | Claims 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).
- Create a random
code_verifierand its SHA-256code_challenge. - Send the user to
/oauth/authorizewithresponse_type=code,client_id,redirect_uri,scope,state,code_challengeandcode_challenge_method=S256. - The workspace admin approves the scopes.
- inaiy redirects back with a short-lived
codeand yourstate. Check thatstatematches. - Exchange the code at
/oauth/tokenwithgrant_type=authorization_codeand thecode_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_VERIFIERToken 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
| Scope | Grants |
|---|---|
contacts.read | View contacts and their details. |
contacts.write | Create, update, and delete contacts. |
conversations.read | View conversations and their metadata. |
conversations.write | Update, assign, and modify conversations. |
messages.read | View messages within conversations. |
messages.write | Send messages on your behalf. |
media.read | View and download uploaded media files. |
media.write | Upload media files for messages and template headers. |
templates.read | View approved message templates. |
broadcasts.read | View broadcast campaigns and their status. |
broadcasts.write | Create and manage broadcast campaigns. |
catalog.write | Create and update commerce catalog products via the Public API. |
channels.read | View connected WhatsApp, Instagram, and Messenger channels. |
team.read | View agents and teams in the workspace. |
analytics.read | View messaging, template, broadcast, inbox, commerce, drip, AI agent, Public API usage, and plan usage analytics. |
webhooks.read | Reserved for the upcoming webhook management API; no Public API endpoint uses it yet. |
webhooks.write | Reserved 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.