Skip to content
Guides

Authentication

Request, use, and renew OAuth tokens without mixing applications and API keys.

Auth issues OAuth 2.0 tokens. Protected endpoints receive the token in Authorization; public endpoints do not need one. Check the security section for each operation in the reference.

Your serverthe integrationAuthauth.ecomiq.peAdmin APIapi.ecomiq.pe1POST /connect/tokengrant_type=client_credentials200 access_tokenwith expires_in2GET /v1/catalog/productsAuthorization: Bearer200 dataonce it expires, back to step 1The secret only ever travels to the token issuer, never to the API

Application credentials

An OAuth application created in the dashboard provides a client_id and client_secret. The secret identifies a server, so it must not reach a browser or a distributed application.

An API key created with POST /v1/api-keys belongs to the UCP service, whose reference is not published yet.

It cannot be used at /connect/token, and no Admin, Storefront, or Auth operation accepts it.

Use the Bearer token shown by each operation for those APIs.

Token for an Admin integration

Use client_credentials and include the api_admin scope:

curl -X POST https://auth.ecomiq.pe/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=$ECOMIQ_CLIENT_ID" \
  -d "client_secret=$ECOMIQ_CLIENT_SECRET" \
  -d "scope=api_admin"
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6...",
  "token_type": "Bearer",
  "expires_in": 3600
}

expires_in is the lifetime in seconds for that response. Calculate expiration from this value instead of assuming a fixed duration.

Use the token

curl "https://api.ecomiq.pe/api/v1/catalog/products?limit=25" \
  -H "Authorization: Bearer $ECOMIQ_TOKEN"

Admin also needs store context and, when applicable, seller context. In the public workflow documented here, that context comes from token claims. See Context and hierarchy.

Grants

GrantUse
client_credentialsA server acts as the application. It requires a confidential client and does not create a user session.
authorization_codeA user signs in and authorizes an application configured for this flow.
refresh_tokenRenews a session when the application and issued token support this grant.
passwordOnly explicitly configured first-party clients. Do not use it for third-party integrations.

The application defines which grants and scopes it accepts. Do not send a grant only because it appears in this table.

Renewal

client_credentials does not need a refresh token: request another access token before the current one expires. Cache the token per process and use a short margin to avoid sending it while it expires.

let cached: { token: string; expiresAt: number } | undefined;

export async function getToken(): Promise<string> {
  if (cached && Date.now() < cached.expiresAt - 60_000) {
    return cached.token;
  }

  const body = new URLSearchParams({
    grant_type: "client_credentials",
    client_id: process.env.ECOMIQ_CLIENT_ID!,
    client_secret: process.env.ECOMIQ_CLIENT_SECRET!,
    scope: "api_admin",
  });

  const response = await fetch("https://auth.ecomiq.pe/connect/token", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body,
  });

  if (!response.ok) throw new Error(`OAuth HTTP ${response.status}`);

  const payload = await response.json();
  cached = {
    token: payload.access_token,
    expiresAt: Date.now() + payload.expires_in * 1000,
  };

  return cached.token;
}

Coordinate renewal if several processes share credentials. This prevents a burst of simultaneous token requests.

Authentication failures

  • 401 means the endpoint did not receive a valid credential.
  • 403 means the identity was accepted, but a policy, scope, permission, or context blocked the operation.
  • /connect/token returns OAuth errors such as invalid_client or invalid_grant; do not assume it uses Problem Details or a code field.

Do not log the token, secret, or complete body of an OAuth response.

On this page