OAuth Apps
Build third-party applications that connect to WhaleTools stores. OAuth 2.0 with PKCE for secure authorization.
Overview
The WhaleTools OAuth platform lets third-party developers build applications that access store data on behalf of merchants. The flow uses OAuth 2.0 Authorization Code with Proof Key for Code Exchange (PKCE), ensuring secure authorization without exposing client secrets in public clients.
- 1.Register your application and receive a
client_id. - 2.Redirect the merchant to the authorization endpoint with requested scopes.
- 3.The merchant approves access and is redirected back with an authorization code.
- 4.Exchange the code for an access token and refresh token.
- 5.Use the access token to call the WhaleTools API on behalf of the merchant.
Register an Application
Register your OAuth application to receive a client_id. Provide one or more redirect URIs and the scopes your app requires.
whale.oauth.applications.create({
name: "My Commerce App",
redirect_uris: [
"https://myapp.com/callback",
"http://localhost:3000/callback"
],
scopes: ["read:products", "write:orders", "read:customers"]
})
// Response
{
"object": "oauth_application",
"id": "app_01HX7G8K2M...",
"name": "My Commerce App",
"client_id": "woa_live_a1b2c3d4e5f6...",
"redirect_uris": [
"https://myapp.com/callback",
"http://localhost:3000/callback"
],
"scopes": ["read:products", "write:orders", "read:customers"],
"created_at": "2026-03-10T12:00:00.000Z"
}Authorization Flow
WhaleTools uses the Authorization Code flow with PKCE. Generate a code verifier and challenge before redirecting the user.
Step 1: Generate PKCE Parameters
import crypto from 'crypto';
// Generate a random code verifier (43-128 chars)
const codeVerifier = crypto.randomBytes(32).toString('base64url');
// Create the code challenge (S256)
const codeChallenge = crypto
.createHash('sha256')
.update(codeVerifier)
.digest('base64url');
// Store codeVerifier in session — you'll need it in Step 3Step 2: Redirect to Authorization
Send the merchant to the WhaleTools authorization page. Include a state parameter to prevent CSRF attacks.
https://vm.whaletools.cloud/oauth/authorize?
client_id=woa_live_a1b2c3d4e5f6...&
redirect_uri=https://myapp.com/callback&
scope=read:products write:orders read:customers&
state=random_csrf_token&
code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&
code_challenge_method=S256&
response_type=codeStep 3: Handle the Callback
After the merchant approves, they are redirected to your redirect_uri with an authorization code. Verify the state parameter matches what you sent.
// Callback URL:
// https://myapp.com/callback?code=auth_code_here&state=random_csrf_token
// Verify state matches your session
if (params.state !== session.oauthState) {
throw new Error('CSRF validation failed');
}Step 4: Exchange Code for Tokens
const response = await fetch('https://vm.whaletools.cloud/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
code: 'auth_code_here',
client_id: 'woa_live_a1b2c3d4e5f6...',
redirect_uri: 'https://myapp.com/callback',
code_verifier: codeVerifier // from Step 1
})
});
// Response
{
"access_token": "wat_a1b2c3d4...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "wrt_x9y8z7w6...",
"scope": "read:products write:orders read:customers",
"store_id": "cd2e1122-d511-4edb-be5d-..."
}Scopes
Request only the scopes your application needs. Merchants see exactly which permissions your app is requesting during the authorization flow.
| Scope | Description |
|---|---|
| read:products | View products, variants, and collections. |
| write:products | Create, update, and delete products. |
| read:orders | View orders, line items, and fulfillments. |
| write:orders | Create, update, and cancel orders. |
| read:customers | View customer profiles and segments. |
| write:customers | Create and update customer records. |
| read:inventory | View stock levels and locations. |
| write:inventory | Adjust stock and transfer inventory. |
| read:analytics | View sales, traffic, and conversion data. |
| read:media | View media files and metadata. |
| write:media | Upload and manage media assets. |
| read:workflows | View automation workflows. |
| write:workflows | Create and manage workflows. |
| read:agents | View AI agent configurations. |
| write:agents | Create and configure AI agents. |
Token Lifecycle
Access tokens are short-lived for security. Use refresh tokens to obtain new access tokens without re-prompting the merchant.
| Token | Lifetime | Notes |
|---|---|---|
| Access token | 1 hour | Used in Authorization: Bearer header. |
| Refresh token | 30 days | Single-use. A new refresh token is issued with each refresh. |
| Authorization code | 10 minutes | Single-use. Must be exchanged promptly. |
Refreshing Tokens
const response = await fetch('https://vm.whaletools.cloud/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'refresh_token',
client_id: 'woa_live_a1b2c3d4e5f6...',
refresh_token: 'wrt_x9y8z7w6...'
})
});
// Response
{
"access_token": "wat_new_token...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "wrt_new_refresh...",
"scope": "read:products write:orders read:customers"
}Audit Log
Monitor all OAuth authorization events for your application. The audit log tracks grants, revocations, token refreshes, and failed authorization attempts.
GET /v1/oauth/audit-log?application_id=app_01HX7G8K2M...
// Response
{
"object": "list",
"data": [
{
"id": "evt_01HX...",
"type": "oauth.token.granted",
"application_id": "app_01HX7G8K2M...",
"store_id": "cd2e1122-d511-...",
"scopes": ["read:products", "write:orders"],
"ip_address": "203.0.113.42",
"created_at": "2026-03-10T14:30:00.000Z"
},
{
"id": "evt_01HY...",
"type": "oauth.token.refreshed",
"application_id": "app_01HX7G8K2M...",
"store_id": "cd2e1122-d511-...",
"created_at": "2026-03-10T15:31:00.000Z"
},
{
"id": "evt_01HZ...",
"type": "oauth.authorization.revoked",
"application_id": "app_01HX7G8K2M...",
"store_id": "cd2e1122-d511-...",
"revoked_by": "merchant",
"created_at": "2026-03-10T16:00:00.000Z"
}
]
}API Reference
| Method | Path | Description |
|---|---|---|
| POST | /v1/oauth/applications | Register a new OAuth application. |
| GET | /v1/oauth/applications | List your registered applications. |
| GET | /v1/oauth/applications/:id | Get application details. |
| PATCH | /v1/oauth/applications/:id | Update application settings. |
| DELETE | /v1/oauth/applications/:id | Delete an application. |
| GET | /oauth/authorize | Authorization endpoint (user-facing). |
| POST | /oauth/token | Exchange code or refresh token for access token. |
| POST | /oauth/revoke | Revoke an access or refresh token. |
| GET | /v1/oauth/applications/:id/authorizations | List active authorizations for an app. |
| GET | /v1/oauth/audit-log | View OAuth authorization events. |