Error handling
Error response format
Section titled “Error response format”All error responses return JSON with three fields:
{ "title": "not_found", "detail": "Not found.", "status": 404}| Field | Type | Description |
|---|---|---|
title | string | Machine-readable error code — use this for programmatic handling |
detail | string | array | Human-readable description, or field-level validation errors (see below) |
status | integer | HTTP status code (mirrors the response status) |
Validation errors (400)
Section titled “Validation errors (400)”When input validation fails, detail is an array of objects — one per invalid field. Each object maps the field name to a list of error messages:
{ "title": "invalid", "detail": [ { "refresh_rate": [ "A valid number is required.", "Ensure this value is greater than 0." ] }, { "max_width": [ "Ensure this value is greater than or equal to 1." ] } ], "status": 400}Non-field errors (e.g. a malformed request body) return detail as a plain string:
{ "title": "invalid", "detail": "Invalid hash.", "status": 400}HTTP status codes
Section titled “HTTP status codes”| Status | title | When it occurs |
|---|---|---|
400 | invalid | Request validation failed — field errors in detail |
401 | not_authenticated | Missing or invalid authorization credentials |
403 | permission_denied | Authenticated but not allowed to access this resource |
404 | not_found | Resource does not exist, or a required service is not active on the camera |
405 | method_not_allowed | HTTP method not supported on this endpoint |
429 | throttled | Rate limit exceeded — see Rate limiting |
502 | bad_gateway | Angelcam could not reach an upstream service (e.g. camera or Arrow client offline) |
503 | bad_gateway | Service temporarily unavailable — retry after a short wait |
Full schema definitions are available in the API Reference.
Rate limiting
Section titled “Rate limiting”All API calls count toward per-account rate limits tracked across all authentication methods:
- 20 requests per minute
- 1 000 requests per day
When the limit is exceeded, the API returns 429 with a JSON body indicating how long to wait:
{ "title": "throttled", "status": 429, "detail": "Request was throttled. Expected available in 7 seconds."}Parse the wait time from the detail string, or simply retry after a fixed delay. Implement exponential backoff if you receive multiple consecutive 429 responses.
To raise your limits, contact support. Higher limits are available on the Business and Flex plans — see plans and pricing.
Common mistakes
Section titled “Common mistakes”401 on a seemingly valid token OAuth2 access tokens expire after 10 hours. Refresh the access token using the refresh token before retrying. See Authentication.
404 on a recording or timeline endpoint
Recording endpoints return 404 when the Cloud Recording service is not active on that camera — not only when the camera doesn’t exist. Activate the service first or check that it’s assigned to the correct camera.
404 on a valid-looking URL
All endpoint URLs require a trailing slash. /cameras/123/recording returns 404; the correct URL is /cameras/123/recording/. See API conventions.
403 due to missing scope
Each endpoint requires a specific scope (e.g. camera_access, recording_access). Scopes are configured when creating an OAuth2 token and also when creating a Personal Access Token in the MyAngelcam Dashboard. If the token was issued without the required scope, the API returns 403 even though the credentials are valid. Check the token’s scopes against the scopes listed in the API Reference for that endpoint.
403 in another user’s space A user can be a member of multiple spaces with different permission levels. When the active space belongs to another user, the current user may not have permission to perform certain actions. Use the Get space permissions endpoint to inspect what the current user can do in the active space.