Errors
Error responses follow a single envelope: { "error": { "code", "message", "request_id" } }. Always switch on code — the message field is for humans and may evolve.
Codes
| UNAUTHORIZED | 401 | Missing or invalid bearer token. |
| FEATURE_FORBIDDEN | 403 | Your plan tier does not include this feature. |
| BAD_REQUEST | 400 | Request validation failed (parameter out of range, malformed body, etc.). |
| INVALID_CURSOR | 400 | Cursor is tampered, expired, or scoped to a different route. |
| RESOURCE_NOT_FOUND | 404 | The requested subreddit, post, user, or webhook doesn’t exist. |
| INSUFFICIENT_DATA | 425 | Trend signal can’t be computed yet — the subreddit needs more history (typically the first few hours after track). |
| WEBHOOK_DESTINATION_BLOCKED | 400 | Destination URL fails the SSRF / port allowlist policy. |
| RATE_LIMITED | 429 | Burst or monthly ceiling exceeded. Honour the Retry-After header. |
| UPSTREAM_ERROR | 502 | Reddit returned a non-recoverable error. Safe to retry with backoff. |
Examples
400 BAD_REQUEST
{ "error": { "code": "BAD_REQUEST", "message": "request validation failed", "request_id": "<redacted>", "details": { "errors": [ { "loc": [ "query", "limit" ],, "type": "less_than_equal", "msg": "Input should be less than or equal to 100" } ] } } }
400 INVALID_CURSOR
{ "error": { "code": "INVALID_CURSOR", "message": "cursor is missing, malformed, expired, or signed for a different route", "request_id": "<redacted>" } }
404 RESOURCE_NOT_FOUND
{ "error": { "code": "RESOURCE_NOT_FOUND", "message": "Not Found", "request_id": "<redacted>" } }
400 WEBHOOK_DESTINATION_BLOCKED
{ "error": { "code": "WEBHOOK_DESTINATION_BLOCKED", "message": "address 127.0.0.1 is not a public IP", "request_id": "<redacted>" } }