Authentication
All requests to the Tracepos Public API must be authenticated using the Enterprise Dual-Key System. This model provides secure, stateless authentication while tightly binding every transaction to its specific warehouse branch and tenant company.
Dual-Key Architecture
Unlike platforms that use a single global token, Tracepos separates identity from secret authorization:
+--------------------------+
| Tracepos Public API |
+--------------------------+
|
+--------------------------+ |
| Client Request | v
| Headers: | ---------> [PublicApiKeyMiddleware]
| X-Tracepos-Public-Key | - 1. Look up WarehouseApiKey by Public Key
| X-Tracepos-Secret-Key | - 2. Decrypt secret_hash & verify Secret Key
+--------------------------+ - 3. Check status == '1' (Active)
- 4. Verify SaaS tenant subscription validity
- 5. Inject api_warehouse_id & api_user_id
|
v
+--------------------------+
| Controller Execution |
| (Isolated to Warehouse) |
+--------------------------+
1. X-Tracepos-Public-Key
- Prefix:
Trp-pk-... - Purpose: Identifies your terminal, integration client, and resolves the warehouse branch context.
- Exposure: Safe to store on device configuration files (though keep private where possible).
2. X-Tracepos-Secret-Key
- Prefix:
Trp-sk-... - Purpose: Cryptographically authenticates the caller against the encrypted server-side credential.
- Storage: Stored in the Tracepos database as an AES-256 encrypted payload (
secret_hash). - Exposure: Strictly Confidential. Must only be stored in secure backend environment variables, hardware security modules (HSM), or server keystores. Never embed inside client-side JavaScript, mobile frontend bundles, or public repositories.
Required Request Headers
Every request must transmit the following headers:
| Header | Type | Description | Example |
|---|---|---|---|
X-Tracepos-Public-Key | String | Your warehouse Public Key | Trp-pk-9b4f2c018a... |
X-Tracepos-Secret-Key | String | Your warehouse Secret Key | Trp-sk-e72d8a55c1... |
Accept | String | Must always be JSON | application/json |
Content-Type | String | Required for POST, PUT, PATCH | application/json |
Generating API Keys in Tracepos
- Go to Settings → API Keys in your Tracepos sidebar.
- Click Generate New API Key.
- Fill in:
- Key Name: e.g.,
Opay Smart POS - Cashier Counter 2 - Warehouse: Select which physical branch or online fulfillment warehouse this key manages.
- Rate Limit: Set daily or per-minute request limits.
- Key Name: e.g.,
- Save the key. Tracepos displays the generated
Secret Keyonce. - If you need to view the secret key later, Tracepos requires your Company Primary Administrator Password before revealing it, mitigating accidental staff disclosure.
Code Samples
cURL
curl -X GET "https://app.tracepos.net/api/v1/public/warehouses" \
-H "X-Tracepos-Public-Key: Trp-pk-YOUR_PUBLIC_KEY" \
-H "X-Tracepos-Secret-Key: Trp-sk-YOUR_SECRET_KEY" \
-H "Accept: application/json"
Node.js (Axios)
const axios = require('axios');
const client = axios.create({
baseURL: 'https://app.tracepos.net/api/v1/public',
headers: {
'X-Tracepos-Public-Key': process.env.TRACEPOS_PUBLIC_KEY,
'X-Tracepos-Secret-Key': process.env.TRACEPOS_SECRET_KEY,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
// Example authenticated call
client.get('/customers')
.then(res => console.log('Authenticated successfully:', res.data))
.catch(err => console.error('Auth Failed:', err.response?.data || err.message));
Python (Requests)
import os
import requests
HEADERS = {
"X-Tracepos-Public-Key": os.environ["TRACEPOS_PUBLIC_KEY"],
"X-Tracepos-Secret-Key": os.environ["TRACEPOS_SECRET_KEY"],
"Accept": "application/json",
"Content-Type": "application/json",
}
response = requests.get(
"https://app.tracepos.net/api/v1/public/warehouses",
headers=HEADERS
)
print(response.json())
PHP (Guzzle)
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'https://app.tracepos.net/api/v1/public/',
'headers' => [
'X-Tracepos-Public-Key' => getenv('TRACEPOS_PUBLIC_KEY'),
'X-Tracepos-Secret-Key' => getenv('TRACEPOS_SECRET_KEY'),
'Accept' => 'application/json',
'Content-Type' => 'application/json',
]
]);
$response = $client->get('warehouses');
echo $response->getBody();
Java (OkHttp)
import okhttp3.*;
public class TraceposClient {
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://app.tracepos.net/api/v1/public/warehouses")
.get()
.addHeader("X-Tracepos-Public-Key", System.getenv("TRACEPOS_PUBLIC_KEY"))
.addHeader("X-Tracepos-Secret-Key", System.getenv("TRACEPOS_SECRET_KEY"))
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new RuntimeException("Unexpected code " + response);
System.out.println(response.body().string());
}
}
}
Authentication Error Handling
If authentication fails, Tracepos returns an HTTP 401 Unauthorized status with a descriptive message:
Missing Headers
{
"status": "error",
"message": "Authentication failed. Please provide both X-Tracepos-Public-Key and X-Tracepos-Secret-Key headers."
}
Invalid Public Key
{
"status": "error",
"message": "Invalid or inactive Public Key."
}
Invalid Secret Key
{
"status": "error",
"message": "Invalid Secret Key."
}
Expired License
If the merchant's SaaS subscription has expired, the API gatekeeper blocks external writes with HTTP 403 Forbidden:
{
"status": "error",
"message": "Your subscription plan has expired. Please renew your plan to continue using API services."
}
