Skip to main content

Authentication

The Quantaprice API uses OAuth2 with API keys. You first exchange your API key for an access token, then use that token for API calls.

Creating an API Key​

  1. Sign in to your tenant console at https://YOUR_TENANT.quantaprice.com
  2. Open Settings → API Keys
  3. Click Create API Key
  4. Enter a descriptive name for the key (e.g., "Production Server", "Development")
  5. Click Create
Store your secret securely

The client_secret is only shown once when created. Copy it immediately and store it securely. If you lose the secret, you'll need to create a new API key.

API Key Components​

When you create an API key, you receive two values:

ComponentDescriptionExample
client_id24-character hexadecimal identifiera1b2c3d4e5f6a1b2c3d4e5f6
client_secret64-character hexadecimal secret0123456789abcdef...

The client_id is always visible in the console. The client_secret is only shown once at creation time.

A key has full access to its tenant's API, except backups, restores and purging data, which only a person signed in to the console can do. Every user of the tenant, whatever their role, can create and revoke keys; see Users and Sign-in.

Authentication Flow​

Step 1: Exchange API Key for Access Token​

Use the OAuth2 client_credentials grant to exchange your API key for a JWT access token:

curl -X POST "https://login.quantaprice.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=your_client_id" \
-d "client_secret=your_client_secret"

Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900
}

The access token is valid for 15 minutes (900 seconds).

Step 2: Use Access Token for API Calls​

Include the access token in the Authorization header:

curl -X GET "https://YOUR_TENANT.quantaprice.com/api/price/SKU-PRODUCT-001/your-pricelist" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json"

Code Examples​

JavaScript/TypeScript​

const CLIENT_ID = process.env.QUANTAPRICE_CLIENT_ID;
const CLIENT_SECRET = process.env.QUANTAPRICE_CLIENT_SECRET;
const TOKEN_URL = "https://login.quantaprice.com/oauth2/token";
const API_URL = "https://YOUR_TENANT.quantaprice.com/api";

// Cache for access token
let accessToken: string | null = null;
let tokenExpires = 0;

async function getAccessToken(): Promise<string> {
// Return cached token if still valid (with 60s buffer)
if (accessToken && Date.now() < tokenExpires - 60000) {
return accessToken;
}

const response = await fetch(TOKEN_URL, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET
})
});

if (!response.ok) {
throw new Error(`Token request failed: ${response.status}`);
}

const data = await response.json();
accessToken = data.access_token;
tokenExpires = Date.now() + (data.expires_in * 1000);

return accessToken;
}

async function getPrices(sku: string) {
const token = await getAccessToken();

const response = await fetch(`${API_URL}/price/${sku}/your-pricelist`, {
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
}
});

return response.json();
}

Python​

import os
import time
import requests

CLIENT_ID = os.environ.get("QUANTAPRICE_CLIENT_ID")
CLIENT_SECRET = os.environ.get("QUANTAPRICE_CLIENT_SECRET")
TOKEN_URL = "https://login.quantaprice.com/oauth2/token"
API_URL = "https://YOUR_TENANT.quantaprice.com/api"

# Token cache
_access_token = None
_token_expires = 0

def get_access_token():
global _access_token, _token_expires

# Return cached token if still valid (with 60s buffer)
if _access_token and time.time() < _token_expires - 60:
return _access_token

response = requests.post(TOKEN_URL, data={
"grant_type": "client_credentials",
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET
})
response.raise_for_status()

data = response.json()
_access_token = data["access_token"]
_token_expires = time.time() + data["expires_in"]

return _access_token

def get_prices(sku):
token = get_access_token()

response = requests.get(
f"{API_URL}/price/{sku}/your-pricelist",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
)
response.raise_for_status()

return response.json()

Token Refresh​

Access tokens expire after 15 minutes. Your application should:

  1. Cache the token - Don't request a new token for every API call
  2. Track expiration - Store the expires_in value and refresh before it expires
  3. Handle 401 errors - If you receive a 401, request a new token and retry

Managing API Keys​

Viewing Keys​

In Settings → API Keys, you can view all API keys for your tenant, with when each was last used. The client_secret is never displayed after creation.

Revoking Keys​

To revoke an API key:

  1. Open Settings → API Keys in the console
  2. Find the key you want to revoke
  3. Click the Revoke button
  4. Confirm the action

A revoked key can no longer obtain access tokens. Tokens already issued with it remain valid until they expire, at most 15 minutes.

Security Best Practices​

  • Never commit API keys to version control. Use environment variables or a secrets manager.
  • Use separate keys for different environments. Create distinct keys for development, staging, and production.
  • Rotate keys periodically. Create a new key, update your applications, then revoke the old key.
  • Revoke unused keys. Remove keys that are no longer needed.
  • Monitor key usage. Check "Last used" in Settings → API Keys to identify inactive keys.
  • Cache tokens appropriately. Request new tokens only when needed, not on every API call.

Error Responses​

Status CodeDescription
401 UnauthorizedInvalid API key, expired token, or missing authorization
403 ForbiddenValid token but insufficient permissions for the resource

Example error response:

{
"error": "invalid_client",
"error_description": "Invalid client credentials"
}

See also​