Errors and limits
HoneyNotify uses HTTP status codes for the broad outcome and a stable JSON envelope for actionable error details.
Error envelope#
{
"error": {
"code": "validation_error",
"message": "target.type is invalid",
"details": {}
},
"request_id": "c1a26486-1da3-4fcc-9273-623ad0d52f68"
}
Log the status, error.code, and request_id. The human-readable message may become clearer over time, so application branching should use the status and code rather than exact message text.
Error codes#
| Code | Typical status | Meaning |
|---|---|---|
invalid_json |
400 |
Body is malformed JSON or is not a JSON object |
unauthorised |
401 |
Bearer key is missing, invalid, revoked, or inactive |
insufficient_scope |
403 |
Key is valid but cannot use this route |
not_found |
404 |
Route or app-owned resource does not exist |
payload_too_large |
413 |
Body exceeds the configured request limit |
unsupported_media_type |
415 |
JSON write lacks Content-Type: application/json |
validation_error |
422 |
Field, reference, or resource state is invalid |
rate_limit_exceeded |
429 |
Organisation or app request limit was exceeded |
database_error |
500 |
Request could not be persisted/read |
internal_error |
500 |
Unexpected server failure |
Errors never intentionally include provider credentials, raw API keys, or internal stack traces.
Retry decision#
| Response | Retry? | Approach |
|---|---|---|
| Network timeout/reset | yes | Retry with backoff; reuse notification idempotency key |
400, 413, 415, 422 |
no | Correct the request first |
401, 403 |
no | Correct/rotate the key or scopes first |
404 |
usually no | Verify route, UUID, and app ownership |
429 |
yes | Back off with jitter and reduce concurrency |
500 |
yes | Back off; stop after a bounded number of attempts |
Example schedule: retry after roughly 0.5 s, 1 s, 2 s, and 4 s, adding randomness and a maximum attempt count. Queue failed work for later inspection rather than retrying forever.
Rate limiting#
Every authenticated /v1 request counts against organisation and app limits. The unauthenticated /health and /status endpoints do not. Limited responses include:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
Limits use minute buckets. X-RateLimit-Remaining bottoms out at zero. Spread bulk reads and writes over time, cache slow-changing resources, and avoid polling more often than the resource can reasonably change.
Request and field limits#
The deployment configures a maximum JSON request size (commonly 1 MiB). Notable resource limits include:
| Item | Limit |
|---|---|
| Page size | 250 |
| Idempotency key | 190 characters |
| Notification title | 250 characters |
| Notification body | 4,096 characters |
| Notification actions | 3 |
| TTL | 2,419,200 seconds (28 days) |
| Included/excluded segment IDs | 50 each |
| Segment filter conditions | 50 |
| Segment nesting | 5 levels |
Values in in / not_in |
100 |
| Journey nodes | 100 |
| Journey wait | 2,678,400 seconds (31 days) |
| Webhook event types | 50 |
| Export availability | 24 hours |
Push providers impose additional payload, token, image, and delivery constraints. Keep custom data compact and use URLs for remote media.
Debugging a failed request#
- Capture the HTTP status, response JSON, and
X-Request-ID. - Confirm the request went to
https://api.honeynotify.com/v1/.... - Check bearer key type and required scope in the API reference.
- Confirm JSON is an object and the content type is correct.
- Validate UUIDs, timestamps, enum values, and app ownership.
- For notification retries, preserve the original
Idempotency-Key. - If the failure is server-side and persists, provide the request ID and approximate UTC time to support—never provide the full API key.
