| name | commerce-api |
| description | Authenticate with the GoDaddy Commerce Platform using OAuth2 client credentials. Covers the /v2/oauth2/token endpoint, environments (ote, prod), required headers, scopes, and monetary value formats. Always collect client ID, client secret, store ID, and environment from the user before making API calls. Ensures @godaddy/react (FE checkout components) and @godaddy/cli (API discovery) are installed and up to date before proceeding. For API discovery and schema introspection use @godaddy/cli (godaddy api list, godaddy api describe, godaddy api search) to find endpoints and required scopes. For checkout session creation use the Checkout API.
|
| type | core |
| library | @godaddy/react |
| sources | ["godaddy/javascript:packages/react/skills/commerce-api/SKILL.md"] |
GoDaddy Commerce API — Authentication & Discovery
Setup
Ensure @godaddy/react is installed and up to date
The @godaddy/react package provides the React checkout components,
hooks, and utilities used throughout this skill. Before proceeding,
verify it is installed and running the latest version so you have the
most recent component APIs and bug fixes.
Step 1 — Check for an existing installation:
pnpm ls @godaddy/react 2>/dev/null
npm ls -g @godaddy/react --depth=0 2>/dev/null
If the package is found, skip to Step 3 (update to latest).
Step 2 — Install (if not found):
Ask the user whether they want @godaddy/react installed as a
production dependency (most common for frontend apps), a
dev dependency, or globally. Explain the trade-offs:
| Option | Command | When to choose |
|---|
| Dependency | pnpm add @godaddy/react@latest | App ships checkout UI — components are needed at runtime |
| Dev dependency | pnpm add -D @godaddy/react@latest | Only used during development/build (e.g., design system tooling) |
| Global | npm install -g @godaddy/react@latest | Quick prototyping outside a project |
Wait for the user's preference before running the install command.
Step 3 — Update to the latest version (if already installed):
Capture the currently installed version before updating so you can
detect whether the package actually changed:
OLD_VERSION=$(pnpm ls @godaddy/react --depth=0 2>/dev/null | grep @godaddy/react || echo "none")
pnpm up @godaddy/react@latest
npm install -g @godaddy/react@latest
Use the same install location (project vs global) that was detected or
chosen in the earlier steps.
Step 4 — Verify:
pnpm ls @godaddy/react
Confirm the listed version matches the latest release on npm. The
package also ships @godaddy/localizations as a dependency — it will
be installed automatically.
Step 5 — Re-read this skill if the package was updated:
The @godaddy/react package ships its skill files in the skills/
directory. When the package version changes, the skill instructions
may have been updated (new components, changed APIs, revised patterns).
If the version changed after Step 3 (i.e. the new version differs
from OLD_VERSION), you must re-read this skill file before
continuing so you are operating on the latest instructions:
# Installed as a project dependency (most common)
node_modules/@godaddy/react/skills/commerce-api/SKILL.md
# Installed globally (npm root -g to find prefix)
$(npm root -g)/@godaddy/react/skills/commerce-api/SKILL.md
After re-reading, restart the Setup flow from the top — the new
version may have added prerequisites, changed credential requirements,
or introduced new sections.
Why this matters: Skill files are versioned with the package. If
you skip re-reading after an update, you may follow stale instructions
that reference deprecated APIs, missing components, or outdated
patterns. Always treat a version bump as a signal to reload.
Collect credentials
Connecting to the GoDaddy Commerce Platform requires three pieces of
information from the user. Always ask for these before making any API
calls:
- OAuth client ID and client secret — from their GoDaddy app
- Store ID (UUID) — identifies the merchant store
- Environment —
ote or prod (if not specified, default to ote)
If the user provides a custom API host (e.g., for an internal environment),
use it directly instead of the mappings below.
Environments:
| Environment | API Host | Token Endpoint |
|---|
| ote | api.ote-godaddy.com | https://api.ote-godaddy.com/v2/oauth2/token |
| prod | api.godaddy.com | https://api.godaddy.com/v2/oauth2/token |
Obtain an OAuth token using the client credentials grant with form
parameters:
async function getAccessToken(env: 'ote' | 'prod' = 'ote'): Promise<string> {
const host = env === 'prod' ? 'api.godaddy.com' : 'api.ote-godaddy.com';
const clientId = process.env.OAUTH_CLIENT_ID!;
const clientSecret = process.env.OAUTH_CLIENT_SECRET!;
const response = await fetch(`https://${host}/v2/oauth2/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: clientId,
client_secret: clientSecret,
grant_type: 'client_credentials',
scope: 'commerce.product:read commerce.product:write commerce.order:read',
}),
});
if (!response.ok) {
const text = await response.text();
throw new Error(`OAuth token request failed: ${response.status} — ${text}`);
}
const data = await response.json();
return data.access_token;
}
Tokens are short-lived (~1 hour). Cache and refresh before expiry.
Required headers for all API requests:
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'x-store-id': storeId,
'user-agent': 'your-app/1.0.0 (GoDaddy Commerce Platform)',
};
OAuth scopes — request only the scopes your application needs. Use
godaddy api describe <endpoint> to find the exact scopes required for
each endpoint. If a scope is not provisioned for your OAuth app, the
token request returns invalid_scope.
| Scope | Purpose |
|---|
commerce.product:read | Read catalog/SKU data |
commerce.product:write | Create and update catalog data |
commerce.order:read | Read order data |
Monetary values — all money amounts in API responses are in minor
units (cents). For example, "value": 2500 with "currencyCode": "USD"
means $25.00, not $2,500. Always divide by 100 for USD display.
Core Patterns
Discover APIs with @godaddy/cli
Use the @godaddy/cli package (https://www.npmjs.com/package/@godaddy/cli)
to discover available endpoints, inspect their schemas, and identify
required scopes. The CLI is a discovery tool only — use the OAuth
token (see Setup above) to make actual API calls in your application code.
Ensure @godaddy/cli is installed and up to date
Before using any godaddy api commands, verify the CLI is available and
running the latest version so you have the most recent API schemas for
discovery.
Step 1 — Check for an existing installation:
npm ls -g @godaddy/cli --depth=0 2>/dev/null
pnpm ls @godaddy/cli 2>/dev/null
If either command shows @godaddy/cli is installed, skip to Step 3
(update to latest).
Step 2 — Install (if not found):
Ask the user whether they want the CLI installed globally or as a
dev dependency in the project. Explain the trade-offs:
| Option | Command | When to choose |
|---|
| Global | npm install -g @godaddy/cli@latest | Shared across projects; available everywhere |
| Dev dependency | pnpm add -Dw @godaddy/cli@latest | Pinned to the repo; consistent across contributors |
Wait for the user's preference before running the install command.
Step 3 — Update to the latest version (if already installed):
Always ensure the installed version is up to date so the agent has access
to the latest API schemas:
npm install -g @godaddy/cli@latest
pnpm up -Dw @godaddy/cli@latest
Use the same install location (global vs local) that was detected or
chosen in the earlier steps.
Step 4 — Verify the CLI works:
godaddy --version
If the CLI was installed as a local dev dependency and is not on PATH,
run it via pnpm exec godaddy --version (and prefix all subsequent
godaddy commands with pnpm exec).
Discover available API domains and endpoints:
godaddy api list
godaddy api list --domain catalog-products
godaddy api list --domain orders
godaddy api search checkout
godaddy api search tax
godaddy api describe /location/addresses
godaddy api describe /v1/commerce/stores/{storeId}/orders
All CLI commands return structured JSON with next_actions that suggest
what to run next. Use godaddy api describe to inspect request/response
schemas and required scopes, then use that information to make
authenticated requests with your OAuth token.
Example: calling the orders API directly using the discovered path and scopes
const response = await fetch(
`https://${host}/v1/commerce/stores/${storeId}/orders`,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'x-store-id': storeId,
},
}
);
Note: Most commerce endpoints require {storeId} in the path
(e.g., /v1/commerce/stores/{storeId}/orders,
/v2/commerce/stores/{storeId}/catalog-subgraph). Always check the
endpoint schema with godaddy api describe before implementing.
Create and Update Checkout Sessions
The Checkout API uses a dedicated host: checkout.commerce.api.{host}
import { GraphQLClient } from 'graphql-request';
const checkoutClient = new GraphQLClient(
`https://checkout.commerce.api.ote-godaddy.com/`,
{
headers: {
Authorization: `Bearer ${token}`,
'x-store-id': storeId,
'user-agent': 'my-app/1.0.0 (GoDaddy Commerce Platform)',
},
}
);
const session = await checkoutClient.request(`
mutation CreateCheckoutSession($input: MutationCreateCheckoutSessionInput!) {
createCheckoutSession(input: $input) {
id url status expiresAt
draftOrder {
id number
totals { total { value currencyCode } }
lineItems { edges { node { id name quantity unitPrice { value currencyCode } } } }
}
}
}
`, {
input: {
storeId,
returnUrl: 'https://example.com/cart',
successUrl: 'https://example.com/thank-you',
lineItems: [
{ skuId: 'sku-123', quantity: 1 },
],
},
});
const updated = await checkoutClient.request(`
mutation UpdateCheckoutSession($id: String!, $input: MutationUpdateCheckoutSessionInput!) {
updateCheckoutSession(id: $id, input: $input) {
id status
}
}
`, {
id: session.createCheckoutSession.id,
input: {
enablePromotionCodes: true,
enableShipping: true,
enableTaxCollection: true,
},
});
Token Caching
let cached = { token: '', expiresAt: 0 };
async function getValidToken(env: 'ote' | 'prod' = 'ote'): Promise<string> {
if (Date.now() < cached.expiresAt - 60_000) return cached.token;
const host = env === 'prod' ? 'api.godaddy.com' : 'api.ote-godaddy.com';
const response = await fetch(`https://${host}/v2/oauth2/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: process.env.OAUTH_CLIENT_ID!,
client_secret: process.env.OAUTH_CLIENT_SECRET!,
grant_type: 'client_credentials',
scope: 'commerce.product:read commerce.order:read',
}),
});
const data = await response.json();
cached = {
token: data.access_token,
expiresAt: Date.now() + data.expires_in * 1000,
};
return cached.token;
}
Common Mistakes
CRITICAL Missing Bearer prefix in Authorization header
Wrong:
headers: { 'Authorization': token }
Correct:
headers: { 'Authorization': `Bearer ${token}` }
The API returns 401 if the Bearer prefix is missing. This is a silent
failure when error handling swallows the status code.
CRITICAL Using wrong token endpoint URL
Wrong:
const tokenUrl = 'https://sso.godaddy.com/v1/token';
Correct:
const tokenUrl = 'https://api.godaddy.com/v2/oauth2/token';
The OAuth token endpoint is /v2/oauth2/token on the API host
(api.godaddy.com or api.ote-godaddy.com). Using any other host or
path returns 404 or 405.
HIGH Omitting scope in token request
Wrong:
body: new URLSearchParams({ client_id: id, client_secret: secret, grant_type: 'client_credentials' })
Correct:
body: new URLSearchParams({
client_id: id, client_secret: secret,
grant_type: 'client_credentials',
scope: 'commerce.product:read commerce.order:read',
})
Omitting scope may return a token without commerce permissions, causing
403 Forbidden on API calls despite having a valid token. Requesting a scope
not provisioned for your OAuth app returns an invalid_scope error.
HIGH Checkout API uses a different host than subgraph APIs
Wrong:
const url = `https://api.ote-godaddy.com/checkout`;
Correct:
const url = `https://checkout.commerce.api.ote-godaddy.com/`;
The Checkout API uses a dedicated subdomain (checkout.commerce.api.{host}),
not a path on the standard API host. Using the wrong host returns 404.
MEDIUM Using expired token without refresh
Wrong:
const token = await getAccessToken();
Correct:
const token = await getValidToken();
Tokens expire in ~1 hour. Cache the token and refresh with a 1-minute
buffer before expires_in elapses. After expiry, requests fail with 401.