Skip to main content
The FlexPrice API uses conventional HTTP status codes and returns structured error responses to indicate the success or failure of requests.

Error Response Format

All errors follow a consistent JSON structure:
Standard Error Response
{
  "success": false,
  "error": {
    "message": "Human-readable error description",
    "internal_error": "machine_readable_code",
    "details": {
      "field": "additional context"
    }
  }
}
success
boolean
Always false for error responses
error
object
Error details object
message
string
Human-readable error message describing what went wrong
internal_error
string
Machine-readable error code for programmatic handling
details
object
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

200
OK
Request succeeded. The response body contains the requested data.
201
Created
Resource created successfully. The response contains the new resource.
204
No Content
Request succeeded with no response body (typically for DELETE operations).

Client Error Codes

400
Bad Request
Invalid request format, missing required fields, or validation errors.
Example
{
  "success": false,
  "error": {
    "message": "Invalid email format",
    "internal_error": "validation_error",
    "details": {
      "field": "email",
      "value": "invalid-email"
    }
  }
}
401
Unauthorized
Missing or invalid authentication credentials.
Example
{
  "success": false,
  "error": {
    "message": "API key required",
    "internal_error": "permission_denied"
  }
}
403
Forbidden
Authentication succeeded but you don’t have permission to access the resource.
Example
{
  "success": false,
  "error": {
    "message": "Insufficient permissions to access this resource",
    "internal_error": "permission_denied"
  }
}
404
Not Found
The requested resource doesn’t exist.
Example
{
  "success": false,
  "error": {
    "message": "Customer not found",
    "internal_error": "not_found",
    "details": {
      "customer_id": "cus_invalid123"
    }
  }
}
409
Conflict
Request conflicts with existing data (duplicate resources, version conflicts).
Example
{
  "success": false,
  "error": {
    "message": "Customer with this external_id already exists",
    "internal_error": "already_exists",
    "details": {
      "external_customer_id": "cus_123"
    }
  }
}
429
Too Many Requests
Rate limit exceeded. Retry after the time specified in Retry-After header.
Example
{
  "success": false,
  "error": {
    "message": "Rate limit exceeded",
    "internal_error": "service_unavailable",
    "details": {
      "retry_after": 60
    }
  }
}

Server Error Codes

500
Internal Server Error
An unexpected error occurred on the server.
Example
{
  "success": false,
  "error": {
    "message": "An internal error occurred",
    "internal_error": "internal_error"
  }
}
503
Service Unavailable
Service is temporarily unavailable (maintenance, overload).
Example
{
  "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

not_found
string
Requested resource doesn’t existHTTP Status: 404
already_exists
string
Resource with the same identifier already existsHTTP Status: 409
version_conflict
string
Optimistic locking failure - resource was modified by another requestHTTP Status: 409

Validation Errors

validation_error
string
Request data failed validation (invalid format, missing required fields)HTTP Status: 400
invalid_operation
string
Operation is not allowed in the current stateHTTP Status: 400Example: Attempting to activate an already-active subscription

Authentication & Authorization

permission_denied
string
Missing authentication or insufficient permissionsHTTP Status: 401 or 403

System Errors

database_error
string
Database operation failedHTTP Status: 500
http_client_error
string
External HTTP request failedHTTP Status: 500
system_error
string
General system errorHTTP Status: 500
internal_error
string
Unexpected internal errorHTTP Status: 500
service_unavailable
string
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

Check Before Deleting
# 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

Retry with Different ID
# 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

Exponential Backoff
# 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

1

Check error codes programmatically

Use the internal_error field to handle specific error types in your code rather than parsing error messages.
2

Implement retry logic

For 500 and 503 errors, implement exponential backoff retry logic. For 429 errors, respect the Retry-After header.
3

Log error details

Include the full error response in your logs, including the details object, to help with debugging.
4

Handle validation errors gracefully

For validation_error responses, display user-friendly messages and highlight specific fields that need correction.
5

Monitor error rates

Track error rates by status code and error type to identify integration issues early.

Common Error Scenarios

Duplicate Customer Creation

Request
POST /v1/customers
{
  "external_customer_id": "existing_customer",
  "name": "Test Corp"
}
Response: 409 Conflict
{
  "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

Request
POST /v1/events
{
  "event_name": "api_call",
  "external_customer_id": "cus_123",
  "meter_id": "invalid_meter"
}
Response: 404 Not Found
{
  "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

Request
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