Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.offthehook.dev/llms.txt

Use this file to discover all available pages before exploring further.

Every error response from the Off the Hook API shares the same JSON shape. The error field contains a stable string code that you can safely switch on in your code — these codes are never repurposed across versions. The message field is a human-readable description intended for logging and debugging, not for display in your UI.

Error response shape

{
  "error": "not_found",
  "message": "subscription not found",
  "detail": null,
  "requestId": "host/reqId-000001"
}
FieldTypeDescription
errorstringStable error code enum — safe to switch on in code
messagestringHuman-readable description of the error
detailobject | nullAdditional structured context for select error codes; null for most errors
requestIdstringUnique identifier for the request — include this when contacting support
The requestId value is also sent as the X-Request-Id response header on every API response, including successful ones. You can extract it from the header without parsing the response body, which is useful in middleware or logging layers.

Error codes

CodeHTTP statusDescription
unauthorized401Missing, malformed, or invalid API key
forbidden403Valid key but no access to this resource
not_found404Subscription or event does not exist
invalid_request400Request body or parameter is malformed
invalid_address400Address is not a valid TRON base58check address
invalid_chain400Chain ID is not a recognized CAIP-2 identifier
chain_not_enabled400Chain ID is valid but not yet active
ssrf_blocked400Destination URL resolves to a blocked private IP range
unsupported_event400Event kind is not recognized or not yet supported
description_too_long400Description field exceeds the character limit
addresses_limit_exceeded400Adding these addresses would exceed the per-subscription limit
idempotency_in_flight409A request with the same Idempotency-Key is still processing
idempotency_conflict409A completed request with the same key returned a different result
invalid_pagination_token400The nextPageToken value is malformed or expired
rate_limited429Too many requests — slow down and retry
internal500Unexpected server error; include requestId when reporting

Error code details

ssrf_blocked

The ssrf_blocked error includes a detail object that identifies exactly which IP and CIDR block caused the rejection. This error occurs both at subscription creation time (when the destination URL is validated) and at delivery time (as a defense against DNS rebinding).
{
  "error": "ssrf_blocked",
  "message": "url resolves to a blocked range 10.0.0.0/8",
  "detail": { "ip": "10.0.0.5", "cidr": "10.0.0.0/8" },
  "requestId": "..."
}
Blocked ranges include 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, and other reserved private address spaces. Use a publicly routable HTTPS URL as your webhook destination. During development, https://webhook.site provides a free public endpoint.

idempotency_in_flight

Returned when you send a second request with an Idempotency-Key that is still being processed by a concurrent request. Wait a moment and retry; the original request will complete shortly.

idempotency_conflict

Returned when a completed request exists for the given Idempotency-Key but its stored response differs from what the current request would produce. This typically means the request body changed between calls using the same key. Use a new unique key for the new request.

internal

An unexpected server error. These are logged and investigated automatically, but including the requestId when you report the issue allows the team to find the exact request in the logs.