The FlexPrice API uses conventional HTTP status codes and returns structured error responses to indicate the success or failure of requests.
All errors follow a consistent JSON structure:
{
"success": false,
"error": {
"message": "Human-readable error description",
"internal_error": "machine_readable_code",
"details": {
"field": "additional context"
}
}
}
Always false for error responses
Error details objectHuman-readable error message describing what went wrong
Machine-readable error code for programmatic handling
Additional context about the error, such as validation failures or specific field errors
HTTP Status Codes
The API uses standard HTTP status codes to indicate request outcomes:
Success Codes
Request succeeded. The response body contains the requested data.
Resource created successfully. The response contains the new resource.
Request succeeded with no response body (typically for DELETE operations).
Client Error Codes
Invalid request format, missing required fields, or validation errors.{
"success": false,
"error": {
"message": "Invalid email format",
"internal_error": "validation_error",
"details": {
"field": "email",
"value": "invalid-email"
}
}
}
Missing or invalid authentication credentials.{
"success": false,
"error": {
"message": "API key required",
"internal_error": "permission_denied"
}
}
Authentication succeeded but you don’t have permission to access the resource.{
"success": false,
"error": {
"message": "Insufficient permissions to access this resource",
"internal_error": "permission_denied"
}
}
The requested resource doesn’t exist.{
"success": false,
"error": {
"message": "Customer not found",
"internal_error": "not_found",
"details": {
"customer_id": "cus_invalid123"
}
}
}
Request conflicts with existing data (duplicate resources, version conflicts).{
"success": false,
"error": {
"message": "Customer with this external_id already exists",
"internal_error": "already_exists",
"details": {
"external_customer_id": "cus_123"
}
}
}
Rate limit exceeded. Retry after the time specified in Retry-After header.{
"success": false,
"error": {
"message": "Rate limit exceeded",
"internal_error": "service_unavailable",
"details": {
"retry_after": 60
}
}
}
Server Error Codes
An unexpected error occurred on the server.{
"success": false,
"error": {
"message": "An internal error occurred",
"internal_error": "internal_error"
}
}
Service is temporarily unavailable (maintenance, overload).{
"success": false,
"error": {
"message": "Service temporarily unavailable",
"internal_error": "service_unavailable"
}
}
Error Codes
The internal_error field contains machine-readable error codes for programmatic handling:
Resource Errors
Requested resource doesn’t existHTTP Status: 404
Resource with the same identifier already existsHTTP Status: 409
Optimistic locking failure - resource was modified by another requestHTTP Status: 409
Validation Errors
Request data failed validation (invalid format, missing required fields)HTTP Status: 400
Operation is not allowed in the current stateHTTP Status: 400Example: Attempting to activate an already-active subscription
Authentication & Authorization
Missing authentication or insufficient permissionsHTTP Status: 401 or 403
System Errors
Database operation failedHTTP Status: 500
External HTTP request failedHTTP Status: 500
General system errorHTTP Status: 500
Unexpected internal errorHTTP Status: 500
Service is temporarily unavailableHTTP Status: 503
Error Handling Examples
Handling Validation Errors
curl -X POST http://localhost:8080/v1/customers \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"external_customer_id": "cus_123",
"email": "invalid-email"
}'
# Response: 400 Bad Request
{
"success": false,
"error": {
"message": "Invalid email format",
"internal_error": "validation_error",
"details": {
"field": "email"
}
}
}
Handling Not Found Errors
# First, check if resource exists
curl -X GET http://localhost:8080/v1/customers/cus_abc123 \
-H "X-API-Key: your-api-key"
# If 404, handle gracefully
# Response: 404 Not Found
{
"success": false,
"error": {
"message": "Customer not found",
"internal_error": "not_found"
}
}
Handling Conflict Errors
# Attempt to create customer
curl -X POST http://localhost:8080/v1/customers \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"external_customer_id": "cus_123",
"name": "Acme Corp"
}'
# If 409, customer already exists
# Response: 409 Conflict
{
"success": false,
"error": {
"message": "Customer with this external_id already exists",
"internal_error": "already_exists",
"details": {
"external_customer_id": "cus_123"
}
}
}
# Option 1: Fetch existing customer
curl -X GET http://localhost:8080/v1/customers/external/cus_123 \
-H "X-API-Key: your-api-key"
# Option 2: Update existing customer
curl -X PUT http://localhost:8080/v1/customers?external_customer_id=cus_123 \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp Updated"}'
Handling Rate Limits
# Request that exceeds rate limit
curl -X POST http://localhost:8080/v1/events/bulk \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"events": [...]}'
# Response: 429 Too Many Requests
# Retry-After: 60
{
"success": false,
"error": {
"message": "Rate limit exceeded",
"internal_error": "service_unavailable"
}
}
# Wait for Retry-After seconds and retry
sleep 60
curl -X POST http://localhost:8080/v1/events/bulk \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"events": [...]}'
Best Practices
Check error codes programmatically
Use the internal_error field to handle specific error types in your code rather than parsing error messages.
Implement retry logic
For 500 and 503 errors, implement exponential backoff retry logic. For 429 errors, respect the Retry-After header.
Log error details
Include the full error response in your logs, including the details object, to help with debugging.
Handle validation errors gracefully
For validation_error responses, display user-friendly messages and highlight specific fields that need correction.
Monitor error rates
Track error rates by status code and error type to identify integration issues early.
Common Error Scenarios
Duplicate Customer Creation
POST /v1/customers
{
"external_customer_id": "existing_customer",
"name": "Test Corp"
}
{
"success": false,
"error": {
"message": "Customer with this external_id already exists",
"internal_error": "already_exists"
}
}
Solution: Use GET /v1/customers/external/{external_id} to fetch the existing customer or PUT to update it.
Invalid Meter Reference
POST /v1/events
{
"event_name": "api_call",
"external_customer_id": "cus_123",
"meter_id": "invalid_meter"
}
{
"success": false,
"error": {
"message": "Meter not found",
"internal_error": "not_found"
}
}
Solution: Verify the meter exists using GET /v1/meters before ingesting events.
Missing Required Field
POST /v1/subscriptions
{
"customer_id": "cus_abc123"
// Missing required plan_id
}
Response: 400 Bad Request
{
"success": false,
"error": {
"message": "plan_id is required",
"internal_error": "validation_error",
"details": {
"field": "plan_id"
}
}
}
Solution: Include all required fields as documented in the API reference.
Next Steps
Authentication
Learn about API key authentication
Pagination
Understand paginated responses