Data Reference
Error Reference

Error Reference

All error responses use the standard FastAPI error envelope:

{
  "detail": "Human-readable description of what went wrong"
}

For validation errors (status 422), detail is an array of objects:

{
  "detail": [
    {
      "loc": ["query", "limit"],
      "msg": "ensure this value is less than or equal to 1000",
      "type": "value_error.number.not_le"
    }
  ]
}

Status code reference

400 Bad Request

The request was understood but contained invalid data.

EndpointCauseDetail message
POST /ingest/csvCSV header columns are wrong or missing"CSV header must include From, To, Town, Super (PMS), Diesel (AGO), Kerosene (IK)"
POST /ingest/csvA date cell cannot be parsed"Invalid date format: <raw value>"
POST /ingest/csvCSV has no data rows"CSV payload contains no rows."

401 Unauthorized

The Authorization header is missing or the token is wrong. Only applies to the ingest endpoint.

{
  "detail": "Invalid authorization token for ingestion endpoint."
}

Fix: provide the correct Authorization: Bearer <token> header.

415 Unsupported Media Type

The file uploaded to POST /ingest/csv is not a CSV.

{
  "detail": "Uploaded file must be a CSV file."
}

Accepted MIME types: text/csv, application/vnd.ms-excel, application/octet-stream.

422 Unprocessable Entity

Query parameter or path parameter validation failed. FastAPI returns a structured array in detail:

{
  "detail": [
    {
      "loc": ["query", "limit"],
      "msg": "ensure this value is less than or equal to 1000",
      "type": "value_error.number.not_le"
    }
  ]
}

Common causes:

ParameterConstraintError
limitMust be between 1 and 1000value_error.number.not_ge / value_error.number.not_le
offsetMust be ≥ 0value_error.number.not_ge
start_date / end_dateMust be valid YYYY-MM-DDvalue_error.date

429 Too Many Requests

The client has exceeded 60 requests in 60 seconds.

{
  "detail": "Rate limit exceeded. Try again later."
}

Wait until your window resets (up to 60 seconds) before retrying. See Rate Limiting for strategies to avoid hitting this limit.

500 Internal Server Error

Returned by GET /health when the database is unreachable:

{
  "detail": "Database unreachable"
}

All other 500 errors represent unexpected server-side failures. If you encounter one consistently, please open an issue.


Retrying safely

  • 400, 401, 415, 422 — do not retry; the request itself is the problem. Fix the request.
  • 429 — wait and retry after the rate limit window resets.
  • 500 — safe to retry with exponential backoff (start at 1 second, cap at 30 seconds). If the error persists after 3 attempts, surface it to the user.