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 account.quantaprice.com
  2. Select your tenant from the dashboard
  3. Navigate to the API Keys section
  4. Click Create API Key
  5. Enter a descriptive name for the key (e.g., "Production Server", "Development")
  6. 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 Account Portal. The client_secret is only shown once at creation time.

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": 3600
}

The access token is valid for 1 hour (3600 seconds).

Step 2: Use Access Token for API Calls

Include the access token in the Authorization header:

curl -X GET "https://api.quantaprice.com/api/v1/prices?sku=PRODUCT-001" \
-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://api.quantaprice.com/api/v1";

// 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}/prices?sku=${sku}`, {
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://api.quantaprice.com/api/v1"

# 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}/prices",
params={"sku": sku},
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
)
response.raise_for_status()

return response.json()

Token Refresh

Access tokens expire after 1 hour. 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 the Account Portal, you can view all API keys for your tenant. Each key shows its client_id, name, creation date, and last usage time. The client_secret is never displayed after creation.

Revoking Keys

To revoke an API key:

  1. Go to the API Keys section in the Account Portal
  2. Find the key you want to revoke
  3. Click the Revoke button
  4. Confirm the action

Revoked keys are immediately invalidated. Any access tokens issued from that key will also stop working.

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 the "Last Used" timestamp in the Account Portal 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"
}