Skip to content

OAuth Token Endpoint

The OAuth token endpoint issues JWT access tokens for authenticating with ShopHero APIs.

Endpoint

POST /oauth/token

Request

Headers

HeaderValueRequired
Content-Typeapplication/x-www-form-urlencodedYes

Body Parameters

ParameterTypeRequiredDescription
grant_typestringYesMust be client_credentials
client_idstringYesYour service account client ID
client_secretstringYesYour service account client secret
scopestringNoSpace-separated list of scopes to request

Example Request

bash
curl -X POST https://identity.retailsuccessplatform.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=9a1b2c3d-4e5f-6789-abcd-ef0123456789" \
  -d "client_secret=Wk3mPqR7vX9bN2cF5hJ8tL0wA4sD6gY1uI3oE" \
  -d "scope=engagehq:content.view engagehq:circulars.view"

Response

Success Response (200 OK)

json
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "expires_at": 1705411200
}
FieldTypeDescription
access_tokenstringJWT token to use for API authentication
token_typestringAlways Bearer
expires_inintegerToken validity in seconds (86400 = 24 hours)
expires_atintegerExpiration as Unix timestamp

Error Responses

Invalid Grant Type (400)

json
{
  "error": "unsupported_grant_type",
  "error_description": "The authorization grant type is not supported. Use 'client_credentials'."
}

Missing Parameters (400)

json
{
  "error": "invalid_request",
  "error_description": "The request is missing required parameters: client_id, client_secret"
}

Invalid Client (401)

json
{
  "error": "invalid_client",
  "error_description": "Client authentication failed"
}

Revoked Client (401)

json
{
  "error": "invalid_client",
  "error_description": "The client has been revoked"
}

Invalid Scope (400)

json
{
  "error": "invalid_scope",
  "error_description": "The requested scope is invalid or not authorized"
}

Rate Limited (429)

json
{
  "error": "rate_limit_exceeded",
  "error_description": "Too many requests. Please wait before trying again.",
  "retry_after": 60
}

Using the Token

Include the access token in the Authorization header of API requests:

http
GET /public/v1/content HTTP/1.1
Host: api.engagehq.retailsuccessplatform.com
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...

cURL Example

bash
curl https://api.engagehq.retailsuccessplatform.com/public/v1/content \
  -H "Authorization: Bearer ${ACCESS_TOKEN}"

JavaScript Example

javascript
const response = await fetch('https://api.engagehq.retailsuccessplatform.com/public/v1/content', {
  headers: {
    'Authorization': `Bearer ${accessToken}`,
  },
});

Token Expiration

Access tokens expire after 24 hours (86400 seconds). When a token expires:

  1. API requests return 401 Unauthorized
  2. Request a new token using the same credentials
  3. Update your cached token

Handling Expiration

javascript
async function makeApiCall(url) {
  let response = await fetch(url, {
    headers: { 'Authorization': `Bearer ${token}` }
  });

  if (response.status === 401) {
    // Token expired, get a new one
    token = await getNewToken();

    // Retry the request
    response = await fetch(url, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
  }

  return response.json();
}

Rate Limiting

The token endpoint is rate limited to prevent abuse:

LimitValue
Requests per minute60
Per client IDYes

If you exceed the rate limit, implement exponential backoff:

javascript
async function getTokenWithRetry(maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await getToken();
    } catch (error) {
      if (error.status === 429 && attempt < maxRetries - 1) {
        const waitTime = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }
      throw error;
    }
  }
}

Scope Filtering

The token endpoint filters requested scopes against the service account's allowed scopes:

  • If you request scopes that aren't allowed, you'll receive an invalid_scope error
  • If you don't specify scopes, all allowed scopes are granted
  • You can request a subset of your allowed scopes

Examples

bash
# Request specific scopes
curl -X POST /oauth/token \
  -d "scope=engagehq:content.view"

# Request all allowed scopes (no scope parameter)
curl -X POST /oauth/token \
  -d "grant_type=client_credentials&client_id=...&client_secret=..."

Security Considerations

  1. Use HTTPS - Never send credentials over unencrypted connections
  2. Protect secrets - Never expose client_secret in client-side code
  3. Validate tokens - APIs validate the token signature and expiration
  4. Monitor usage - Check for unauthorized access in audit logs
  5. Rotate regularly - Rotate credentials every 90 days

Changelog
DateChange
2026-02-27Documentation corrections.
2026-01-15Initial publication.

ShopHero CommerceCore Platform