Error Reference
All SpatialFlow API errors follow a consistent JSON format. This page documents every error code, HTTP status pattern, and common error scenarios.
Error Response Format
Every error response includes a detail field with a human-readable message:
{
"detail": "Human-readable error message",
"error_code": "MACHINE_READABLE_CODE",
"details": {}
}
| Field | Type | Required | Description |
|---|---|---|---|
detail | string or array | Yes | Human-readable message (string) or validation errors (array) |
error_code | string | No | Machine-readable identifier for programmatic handling |
details | object | No | Additional context (field errors, limits, etc.) |
Validation Errors
When request body validation fails (HTTP 422), the detail field is an array of error objects instead of a string:
{
"detail": [
{
"type": "missing",
"loc": ["body", "name"],
"msg": "Field required"
},
{
"type": "value_error",
"loc": ["body", "geometry", "type"],
"msg": "Value error, unsupported geometry type"
}
]
}
Each validation error object contains:
| Field | Description |
|---|---|
type | Error type (e.g., missing, value_error, string_too_long) |
loc | Location path as an array (e.g., ["body", "name"]) |
msg | Human-readable error message |
HTTP Status Codes
| Status | Meaning | When It Occurs |
|---|---|---|
| 400 | Bad Request | Invalid input, malformed JSON, business rule violation |
| 401 | Unauthorized | Missing or invalid authentication token or API key |
| 403 | Forbidden | Valid auth but insufficient permissions, or quota exceeded (150%) |
| 404 | Not Found | Resource does not exist or is not accessible to the caller |
| 422 | Unprocessable Entity | Request body fails schema validation |
| 429 | Too Many Requests | Rate limit or quota throttle exceeded |
| 500 | Internal Server Error | Unexpected server failure |
Error Codes Reference
The error_code field provides a machine-readable identifier for programmatic error handling. Not all errors include this field.
| Error Code | HTTP Status | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Global rate limit exceeded (requests per hour) |
RATE_LIMITED | 429 | Event quota soft throttle (usage at 120%) |
QUOTA_EXCEEDED | 403 | Event quota hard cap (usage at 150%) |
INSUFFICIENT_PERMISSIONS | 403 | API key missing required permission scope |
NOT_FOUND | 404 | Requested resource does not exist |
VALIDATION_ERROR | 422 | Request body failed schema validation |
INVALID_GEOMETRY | 400 | Geometry validation failed (invalid type, too many vertices, self-intersection) |
DUPLICATE_RESOURCE | 400 | Resource with the same unique identifier already exists |
Not all errors include an error_code. The detail field is always present and provides a human-readable description. Use error_code for programmatic branching when available, and fall back to detail for display.
Common Error Scenarios
Authentication Failure (401)
curl -i https://api.spatialflow.io/api/v1/geofences \
-H "Authorization: Bearer expired-or-invalid-token"
{
"detail": "Invalid or expired token"
}
Solution: Refresh your JWT token or verify your API key is correct and not revoked.
Rate Limit Exceeded (429)
curl -i https://api.spatialflow.io/api/v1/geofences \
-H "Authorization: Bearer YOUR_API_KEY"
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
Content-Type: application/json
{
"detail": "Rate limit exceeded",
"error_code": "RATE_LIMIT_EXCEEDED",
"details": {
"limit": 1000,
"period_seconds": 3600
}
}
Solution: Wait for the number of seconds specified in the Retry-After header before retrying. See Rate Limiting for retry patterns.
Validation Error (422)
curl -i -X POST https://api.spatialflow.io/api/v1/geofences \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"geometry": {"type": "InvalidType", "coordinates": []}}'
{
"detail": [
{
"type": "missing",
"loc": ["body", "name"],
"msg": "Field required"
},
{
"type": "value_error",
"loc": ["body", "geometry", "type"],
"msg": "Value error, unsupported geometry type"
}
]
}
Solution: Check the loc field in each error to identify which request fields need correction.
Handling Errors in Code
Python
import requests
response = requests.post(
"https://api.spatialflow.io/api/v1/geofences",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"name": "Test"},
)
if not response.ok:
error = response.json()
detail = error.get("detail")
# Validation errors return detail as an array
if isinstance(detail, list):
for err in detail:
print(f" {'.'.join(err['loc'])}: {err['msg']}")
else:
error_code = error.get("error_code")
if error_code == "RATE_LIMIT_EXCEEDED":
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Rate limited. Retry in {retry_after}s")
else:
print(f"Error: {detail}")
TypeScript
async function handleApiError(response: Response): Promise<never> {
const body = await response.json();
if (Array.isArray(body.detail)) {
// Validation errors
const fields = body.detail.map(
(e: { loc: string[]; msg: string }) => `${e.loc.join(".")}: ${e.msg}`,
);
throw new Error(`Validation failed:\n${fields.join("\n")}`);
}
if (body.error_code === "RATE_LIMIT_EXCEEDED") {
const retryAfter = response.headers.get("Retry-After") ?? "60";
throw new Error(`Rate limited. Retry in ${retryAfter}s`);
}
throw new Error(body.detail ?? "Unknown error");
}
See Best Practices for retry patterns and production error handling strategies.