Error Handling
Privé APIs use standard HTTP status codes and structured JSON error responses to help you diagnose issues quickly.
Error Response Format
All errors return a JSON object with this structure:
{
"errorStatus": 401,
"errorCode": "INVALID_CREDENTIALS",
"errorMessage": "The provided username or password is incorrect",
"timestamp": "2026-01-21T23:37:32.569Z"
}
Fields:
errorStatus— Machine-readable error identifier (use for programmatic handling)errorCode— Error type identifiererrorMessage— Human-readable error descriptiontimestamp— Timestamp of the error message (include when contacting support)
HTTP Status Codes
| Code | Status | Meaning | Common Causes |
|---|---|---|---|
| 200 | OK | Request succeeded | - |
| 201 | Created | Resource created successfully | POST requests |
| 400 | Bad Request | Invalid request syntax or parameters | Missing required fields, invalid JSON |
| 401 | Unauthorized | Authentication failed | Invalid token, expired token, no token provided |
| 403 | Forbidden | Authenticated but not authorized | Wrong company credentials, insufficient permissions |
| 404 | Not Found | Resource doesn't exist | Invalid priveKey, deleted entity |
| 409 | Conflict | Resource state conflict | Duplicate creation, concurrent modification |
| 422 | Unprocessable Entity | Request valid but business logic error | Guideline violation, insufficient funds |
| 429 | Too Many Requests | Rate limit exceeded | Too many requests in short period |
| 500 | Internal Server Error | Server-side error | Contact Privé support |
| 503 | Service Unavailable | Temporary outage | Retry with exponential backoff |
Common Error Codes
Authentication Errors
| Error Code | HTTP Status | Description | Solution |
|---|---|---|---|
INVALID_CREDENTIALS | 401 | Wrong username/password | Verify credentials with administrator |
TOKEN_EXPIRED | 401 | JWT token has expired | Re-authenticate to get new token |
TOKEN_INVALID | 401 | Malformed or tampered token | Ensure you're using the complete token from login response |
TOKEN_MISSING | 401 | No Authorization header | Include Authorization: Bearer {token} header |
Authorization Errors
| Error Code | HTTP Status | Description | Solution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | 403 | User lacks required role | Verify you're using correct company credentials |
WRONG_TENANT | 403 | Accessing resource in different tenant | Check {tenant} parameter matches your company |
RESOURCE_ACCESS_DENIED | 403 | Can't access this specific resource | Ensure client/account belongs to your company |
Validation Errors
| Error Code | HTTP Status | Description | Solution |
|---|---|---|---|
MISSING_REQUIRED_FIELD | 400 | Required parameter not provided | Check API reference for required fields |
INVALID_FORMAT | 400 | Parameter in wrong format | e.g., date should be YYYY-MM-DD |
INVALID_VALUE | 400 | Parameter value not allowed | Check allowed values in System Codes |
DUPLICATE_KEY | 409 | Resource with this ID already exists | Use PUT to update instead of POST |
Business Logic Errors
| Error Code | HTTP Status | Description | Solution |
|---|---|---|---|
GUIDELINE_VIOLATION | 422 | Portfolio violates investment guidelines | Review violation details and adjust portfolio |
INSUFFICIENT_BALANCE | 422 | Not enough cash/assets for transaction | Check account balance before trading |
INVALID_STATE_TRANSITION | 422 | Operation not allowed in current state | e.g., can't approve already-approved transaction |
DEPENDENCY_MISSING | 422 | Required linked resource doesn't exist | e.g., risk profile must exist before linking |
Resource Errors
| Error Code | HTTP Status | Description | Solution |
|---|---|---|---|
RESOURCE_NOT_FOUND | 404 | Entity doesn't exist | Verify priveKey/externalKey is correct |
RESOURCE_DELETED | 410 | Resource was previously deleted | Create new resource if needed |
Rate Limiting
| Error Code | HTTP Status | Description | Solution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests | Wait before retrying (see Retry-After header) |
Error Handling Best Practices
1. Check HTTP Status First
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
# Success
data = response.json()
elif response.status_code == 401:
# Re-authenticate
refresh_token()
retry_request()
elif response.status_code >= 500:
# Server error - retry with backoff
retry_with_backoff()
else:
# Client error - log and handle
error = response.json()
log_error(error)
2. Use Error Codes for Logic
try:
response = api_call()
except APIError as e:
if e.code == "GUIDELINE_VIOLATION":
# Show violation details to user
show_violations(e.details)
elif e.code == "INSUFFICIENT_BALANCE":
# Suggest reducing order size
suggest_alternative()
else:
# Generic error handling
log_and_notify(e)
3. Implement Retry Logic
import time
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def create_session_with_retries():
session = requests.Session()
retry_strategy = Retry(
total=3,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "POST", "PUT", "DELETE"],
backoff_factor=1 # Wait 1, 2, 4 seconds
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
return session
4. Log Request IDs
Always log the requestId from error responses:
try:
response = api_call()
except APIError as e:
logger.error(
f"API Error: {e.code} - {e.message}",
extra={"request_id": e.request_id}
)
When contacting Privé support, include the requestId for faster debugging.
Rate Limiting Details
Limits:
- 1000 requests per hour per access token
- Burst limit: 50 requests per minute
- Resource-intensive endpoints (reports, rebalancing) have lower limits
Response Headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1706880000
When Limit Exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Retry after 3600 seconds",
"details": {
"limit": 1000,
"reset": 1706880000
}
}
}
Handling Rate Limits:
import time
def call_with_rate_limit_handling(func):
try:
return func()
except RateLimitError as e:
retry_after = int(e.response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
return func()
Troubleshooting Guide
"401 Unauthorized" Even with Valid Token
Possible Causes:
- Token expired (check
expfield) - Using UAT token in Production (or vice versa)
- Token not properly formatted in header
Debug Steps:
import jwt
# Decode token to check expiration and environment
decoded = jwt.decode(token, options={"verify_signature": False})
print(f"Expires at: {decoded['exp']}")
print(f"Environment: {decoded.get('env', 'unknown')}")
# Verify header format
print(f"Header: Authorization: Bearer {token[:20]}...")
"403 Forbidden" with Valid Authentication
Possible Causes:
- Using wrong company credentials
- Resource belongs to different tenant
- User role lacks required permissions
Solution: Verify you're authenticated as the correct company type for this operation.
"404 Not Found" for Existing Resource
Possible Causes:
- Incorrect
priveKeyorexternalKey - Wrong
{tenant}parameter - Resource was deleted
Debug Steps:
# Try searching by different key types
try:
# Try by priveKey
resource = get_by_prive_key(prive_key)
except NotFoundError:
# Try by externalKey
resource = get_by_external_key(system_type, external_key)
"422 Unprocessable Entity" on Guideline Check
Cause: Portfolio violates investment guidelines
Solution: Parse details field to see specific violations:
try:
result = check_guidelines(portfolio)
except GuidelineViolationError as e:
for violation in e.details['violations']:
print(f"Rule violated: {violation['rule']}")
print(f"Current: {violation['current_value']}")
print(f"Limit: {violation['limit']}")
Getting Help
If you encounter errors not covered here:
- Check Request ID: Include in support request
- Review API Reference: Verify you're using correct parameters
- Search Documentation: Use search bar above
- Contact Support: [email protected]
Support Request Template:
Subject: API Error - [Error Code]
Request ID: req_1234567890abcdef
Endpoint: POST /users/3/tenant123
Timestamp: 2024-01-15T10:30:00Z
Environment: UAT / Production
Error Message:
[Paste full error response]
Steps to Reproduce:
1. [Step 1]
2. [Step 2]
Updated 8 days ago
Next >>
