API Authentication Guide
Complete guide to authenticating with the Picos Health API using API keys and bearer tokens.
Overview
The Picos Health API uses a two-step authentication process:
- Generate an API Key - Create a unique API key in your Account Settings
- Exchange for Bearer Token - Use your API key to get a temporary bearer token
- Make API Requests - Include the bearer token in your request headers
This approach provides enhanced security by allowing you to:
- Generate and revoke API keys on demand
- Use short-lived bearer tokens for individual requests
- Implement rate limiting and usage tracking
- Rotate credentials without updating all your applications
📌 Important: Throughout this guide, you'll see
{org-name}in API URLs. Replace this placeholder with your organization's assigned subdomain (e.g.,eeda,kinexion).
Step 1: Generate an API Key
Via Dashboard
- Log in to Picos Health Dashboard
- Navigate to Account Settings → API Integration
- Click Generate API Key
- Copy your API key immediately (it won't be shown again)
- Store it securely (never commit to version control)
API Key Format
pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
pk_live_prefix indicates a production key- The key is 32 characters of random alphanumeric characters
- Treat it like a password
Step 2: Exchange API Key for Bearer Token
HTTP Request
POST https://{org-name}.api.picoshealth.com/v1/auth/token
Content-Type: application/json
{
"apiKey": "YOUR_API_KEY"
}
Response
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresIn": 3600,
"tokenType": "Bearer"
}
Response Fields:
token- The bearer token to use in API requestsexpiresIn- Token expiration time in seconds (default: 1 hour)tokenType- Always "Bearer"
cURL Example
curl -X POST https://{org-name}.api.picoshealth.com/v1/auth/token \
-H "Content-Type: application/json" \
-d '{
"apiKey": "pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}'
JavaScript Example
async function getAuthToken(apiKey) {
const response = await fetch('https://{org-name}.api.picoshealth.com/v1/auth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
apiKey: apiKey,
}),
});
if (!response.ok) {
throw new Error(`Auth failed: ${response.statusText}`);
}
return response.json();
}
// Usage
const { token, expiresIn } = await getAuthToken('pk_live_...');
console.log(`Token valid for ${expiresIn} seconds`);
Python Example
import requests
import json
def get_auth_token(api_key):
url = "https://{org-name}.api.picoshealth.com/v1/auth/token"
headers = {
"Content-Type": "application/json"
}
payload = {
"apiKey": api_key
}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
return response.json()
# Usage
result = get_auth_token("pk_live_...")
token = result['token']
expires_in = result['expiresIn']
print(f"Token valid for {expires_in} seconds")
Step 3: Make API Requests
Using Bearer Token
Include the token in the Authorization header:
GET https://{org-name}.api.picoshealth.com/v1/users
Authorization: Bearer YOUR_BEARER_TOKEN
JavaScript Fetch Example
async function fetchUsers(token) {
const response = await fetch('https://{org-name}.api.picoshealth.com/v1/users?limit=10', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`API request failed: ${response.statusText}`);
}
return response.json();
}
// Usage
const users = await fetchUsers(token);
console.log(users.docs);
Axios Example
import axios from 'axios';
const api = axios.create({
baseURL: 'https://{org-name}.api.picoshealth.com/v1',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
// Make requests with token automatically included
const response = await api.get('/users', { params: { limit: 10 } });
console.log(response.data.docs);
Python Requests Example
import requests
def make_api_request(token, endpoint, method='GET', params=None, data=None):
url = f"https://{{org-name}}.api.picoshealth.com/v1{endpoint}"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
if method == 'GET':
response = requests.get(url, headers=headers, params=params)
elif method == 'POST':
response = requests.post(url, headers=headers, json=data)
elif method == 'PATCH':
response = requests.patch(url, headers=headers, json=data)
elif method == 'DELETE':
response = requests.delete(url, headers=headers)
response.raise_for_status()
return response.json()
# Usage
users = make_api_request(token, '/users', params={'limit': 10})
print(users['docs'])
Complete Workflow Example
JavaScript
// 1. Get API key from user (stored securely)
const apiKey = process.env.PICOS_API_KEY;
// 2. Exchange for bearer token
async function authenticateAndFetch() {
try {
// Get token
const authResponse = await fetch('https://{org-name}.api.picoshealth.com/v1/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ apiKey }),
});
if (!authResponse.ok) {
throw new Error('Authentication failed');
}
const { token, expiresIn } = await authResponse.json();
console.log(`✓ Authenticated, token valid for ${expiresIn}s`);
// 3. Use token to make API requests
const usersResponse = await fetch('https://{org-name}.api.picoshealth.com/v1/users', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
const users = await usersResponse.json();
console.log(`✓ Retrieved ${users.totalDocs} users`);
console.log('First user:', users.docs[0]);
// Create a new product
const productResponse = await fetch('https://{org-name}.api.picoshealth.com/v1/products', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
title: 'Compression Stockings',
price: 49.99,
currency: 'USD',
status: 'draft',
}),
});
const product = await productResponse.json();
console.log('✓ Created product:', product.id);
} catch (error) {
console.error('Error:', error.message);
}
}
authenticateAndFetch();
Python
import os
import requests
from datetime import datetime, timedelta
class PicosAPIClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://{org-name}.api.picoshealth.com/v1"
self.token = None
self.token_expires = None
def authenticate(self):
"""Exchange API key for bearer token"""
url = f"{self.base_url}/auth/token"
response = requests.post(url, json={"apiKey": self.api_key})
response.raise_for_status()
data = response.json()
self.token = data['token']
self.token_expires = datetime.now() + timedelta(seconds=data['expiresIn'])
print(f"✓ Authenticated, token valid until {self.token_expires}")
def _request(self, method, endpoint, **kwargs):
"""Make authenticated API request"""
if not self.token or datetime.now() >= self.token_expires:
self.authenticate()
url = f"{self.base_url}{endpoint}"
headers = {
"Authorization": f"Bearer {self.token}",
"Content-Type": "application/json",
}
response = requests.request(method, url, headers=headers, **kwargs)
response.raise_for_status()
return response.json()
def get_users(self, limit=10):
"""Get users"""
return self._request("GET", "/users", params={"limit": limit})
def create_product(self, title, price, currency="USD"):
"""Create a product"""
return self._request(
"POST",
"/products",
json={
"title": title,
"price": price,
"currency": currency,
"status": "draft",
},
)
def get_orders(self, limit=20):
"""Get orders"""
return self._request("GET", "/orders", params={"limit": limit})
# Usage
if __name__ == "__main__":
api_key = os.getenv("PICOS_API_KEY")
client = PicosAPIClient(api_key)
# Get users
users_data = client.get_users(limit=5)
print(f"✓ Retrieved {users_data['totalDocs']} users")
print("First user:", users_data['docs'][0])
# Create product
product = client.create_product(
title="Compression Stockings",
price=49.99,
)
print("✓ Created product:", product['id'])
# Get orders
orders_data = client.get_orders(limit=10)
print(f"✓ Retrieved {orders_data['totalDocs']} orders")
Error Handling
Authentication Errors
| Error | Cause | Solution |
|---|---|---|
401 Unauthorized | Invalid or missing API key | Verify API key in Account Settings |
401 Unauthorized | Expired bearer token | Request a new token with your API key |
403 Forbidden | Insufficient permissions | Verify your user role has API access |
429 Too Many Requests | Rate limit exceeded | Implement exponential backoff and retry logic |
Common Responses
Invalid API Key:
{
"error": "Invalid API key",
"code": "INVALID_API_KEY",
"status": 401
}
Expired Token:
{
"error": "Token expired",
"code": "TOKEN_EXPIRED",
"status": 401
}
Permission Denied:
{
"error": "Insufficient permissions",
"code": "FORBIDDEN",
"status": 403
}
Security Best Practices
✅ Do
- Store API keys securely - Use environment variables, secrets managers, or vault systems
- Rotate API keys regularly - Generate new keys monthly or when team members leave
- Use HTTPS only - All requests must use HTTPS
- Keep tokens short-lived - Use the default 1-hour expiration
- Implement rate limiting - Handle 429 responses gracefully
- Log authentication failures - Monitor for suspicious activity
❌ Don't
- Commit API keys to version control - Use
.gitignoreand environment files - Expose API keys in client-side code - Keep keys server-side only
- Share API keys in emails or chat - Use secure credential management
- Use the same key for multiple environments - Generate separate keys per environment
- Leave tokens in browser storage - Keep them in secure, httpOnly cookies
- Log full tokens in production - Only log masked versions
Rate Limiting
All API endpoints have rate limits:
- Standard tier: 100 requests/minute per API key
- Professional tier: 1,000 requests/minute per API key
- Enterprise tier: Custom limits based on agreement
Rate Limit Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1640000000
When Rate Limited (429):
{
"error": "Too many requests",
"retryAfter": 60,
"code": "RATE_LIMITED"
}
Implement exponential backoff retry logic:
async function requestWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error.status === 429 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}
Endpoint Reference
All authenticated endpoints follow this pattern:
{METHOD} https://{org-name}.api.picoshealth.com/v1/{endpoint}
Authorization: Bearer {token}
Content-Type: application/json
Collections
Core Entities
GET /users- List usersGET /users/{id}- Get userPOST /users- Create userPATCH /users/{id}- Update userDELETE /users/{id}- Delete user
Products
GET /products- List productsPOST /products- Create productPATCH /products/{id}- Update product
Orders
GET /orders- List ordersPOST /orders- Create orderPATCH /orders/{id}- Update order status
Cart (new, v2 only - https://{org-name}.api.picoshealth.com/v2/cart)
GET /cart- View the current user's cartPOST /cart- Add a product variant to the cartPATCH /cart/{id}- Update a cart item's quantityDELETE /cart/{id}- Remove a cart item
And many more...
Note: Your bearer token identifies exactly one user (the
subclaim, resolved from your API key). Cart and order-checkout endpoints always act on that user - there is nouserIdparameter to set. See Placing an Order Through the API for the full cart → checkout flow.
Globals
GET /globals/site-settings- Get site settingsPOST /globals/site-settings- Update site settingsGET /globals/organization-settings- Get org settingsGET /globals/wallet- Get wallet config
See Full API Documentation for complete endpoint reference.
Support
For questions or issues:
- Email: api-support@picoshealth.com
- Documentation: API Guide
- Status Page: status.picoshealth.com