API Conventions

API Conventions

This page covers the consistent patterns used across the Brilo API — base URL, how to send requests, what responses look like, how errors are structured, and how pagination works.


Base URL

All API requests go to:

https://api.brilo.tech

All endpoints are prefixed with /api/. For example:

https://api.brilo.tech/api/customers/
https://api.brilo.tech/api/subscriptions/
https://api.brilo.tech/api/credits/

Request Format

Headers

Every request requires:

X-API-KEY: your-api-key
Content-Type: application/json

Request Body

All POST and PATCH request bodies should be JSON:

curl -X POST https://api.brilo.tech/api/customers/ \
  -H "X-API-KEY: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"customer_id": "cust_123", "email": "[email protected]"}'

Response Format

All responses are JSON. Successful responses return the resource object directly — there is no outer wrapper.

{
  "customer_id": "cust_123",
  "email": "[email protected]",
  "customer_name": "Acme Corp",
  "total_amount_due": 0.0,
  "subscriptions": [],
  "invoices": []
}

HTTP Status Codes

CodeMeaning
200 OKRequest succeeded. Response contains the resource.
201 CreatedResource was created. Response contains the new resource.
204 No ContentRequest succeeded with no response body (e.g. deletes).
400 Bad RequestInvalid request. Check the error detail for what's wrong.
401 UnauthorizedMissing or invalid API key.
404 Not FoundThe resource doesn't exist.
409 ConflictRequest conflicts with existing state (e.g. duplicate ID).
422 Unprocessable EntityRequest is well-formed but fails validation.
429 Too Many RequestsRate limit exceeded.
500 Internal Server ErrorSomething went wrong on Brilo's end.

Error Responses

Errors return a JSON body with detail about what went wrong:

{
  "detail": "Customer with id 'cust_123' already exists."
}

For validation errors with multiple fields, errors may be keyed by field:

{
  "email": ["This field is required."],
  "customer_id": ["This field may not be blank."]
}

Always check the detail or field-level messages to understand what to fix before retrying.


Monetary Amounts

All monetary values in the API are represented as decimal numbers in the major currency unit — not cents. 29.00 means $29.00 USD, not $0.29.

{
  "amount": 99.00,
  "currency": {
    "code": "USD",
    "name": "US Dollar",
    "symbol": "$"
  }
}

When specifying amounts in request bodies, use the same decimal format: "recurring_fee": 29.00.


Dates and Timestamps

All dates and timestamps use ISO 8601 format in UTC:

  • Date-only fields: "2024-05-01"
  • Date-time fields: "2024-05-01T10:00:00Z"

When sending dates in request bodies, use these formats. Timestamps in responses are always UTC — convert to local time in your application as needed.


Pagination

List endpoints return paginated results. The response includes the results array and pagination metadata:

{
  "count": 143,
  "next": "https://api.brilo.tech/api/customers/?page=2",
  "previous": null,
  "results": [
    { "customer_id": "cust_001", ... },
    { "customer_id": "cust_002", ... }
  ]
}
FieldDescription
countTotal number of records across all pages
nextURL for the next page, or null if on the last page
previousURL for the previous page, or null if on the first page
resultsArray of records for the current page

Default page size is 50. Pass ?page=N to navigate:

curl "https://api.brilo.tech/api/customers/?page=3" \
  -H "X-API-KEY: your-api-key"

Rate Limits

The API enforces rate limits to protect stability. If you exceed the limit, you'll receive a 429 Too Many Requests response.

The response includes a Retry-After header indicating how many seconds to wait before retrying:

HTTP/1.1 429 Too Many Requests
Retry-After: 10

Best practices:

  • Add exponential backoff with jitter to your retry logic
  • Don't fire large batches of events synchronously — queue and send at a steady rate
  • Use the Verify Events Received endpoint to confirm delivery rather than re-sending blindly

Idempotency

For event tracking, Brilo uses the idempotency_id field to deduplicate requests. If you send the same event twice with the same idempotency_id, Brilo will process it only once.

This means you can safely retry failed event tracking requests without worrying about double-counting usage.

{
  "event_name": "api_call_made",
  "customer_id": "cust_123",
  "idempotency_id": "evt_abc123unique",
  "time_created": "2024-05-01T10:00:00Z"
}

Use a UUID or a deterministic hash as your idempotency_id. See Events & Metering for more detail.


Next Steps


Did this page help you?