All error responses follow a consistent JSON envelope. The data field is set to null, and the error object contains the error details. A request_id is always included for debugging and support purposes.
Every error object has three fields:
- code — a machine-readable error code (e.g., INVALID_API_KEY)
- message — a human-readable description of what went wrong
- status — the HTTP status code for the response
The API uses standard HTTP status codes to indicate the result of each request. The status code directly corresponds to the error.status field in the response body.
| Name | Type | Description |
|---|---|---|
200 | Success | Request completed successfully. The `data` field contains the response payload, and `error` is `null`. |
400 | Bad Request | Invalid request body, missing required fields, malformed JSON, or unsupported engine/parameter value. |
401 | Unauthorized | Missing or invalid API key. The `Authorization` header is absent, does not use the Bearer scheme, or the key hash does not match any stored key. |
402 | Payment Required | Insufficient credits to perform this operation. Check your balance with `jiro status` or the `/v1/status` endpoint. |
403 | Forbidden | The API key is valid but the associated user account is banned or suspended. Contact support for details. |
429 | Too Many Requests | Rate limit exceeded. This can be triggered by any of the four rate limit tiers (per-IP, per-user, per-engine, or global). Check `X-RateLimit-*` headers for details. |
500 | Internal Error | An unexpected server-side error occurred. This is logged automatically. If persistent, contact support with the `request_id`. |
502 | Bad Gateway | The upstream search engine returned an invalid response or timed out. Credits are automatically refunded for these errors. |
503 | Service Unavailable | The engine's circuit breaker is open (5 consecutive failures). The engine will be retried automatically after 60 seconds. Credits are refunded. |
Complete list of machine-readable error codes returned by the API:
| Name | Type | Description |
|---|---|---|
auth_error | 401 | The Authorization header is missing, does not use the Bearer scheme, or the key does not match any stored SHA-256 hash. |
permission_denied | 403 | The API key is valid but belongs to a banned or suspended user account. |
validation_error | 422 | The request body contains invalid fields, missing required parameters, or values outside allowed ranges. |
ssrf_blocked | 400 | The requested URL targets a private/internal IP address or metadata endpoint (169.254.x.x, 10.x.x.x, etc.). SSRF protection is enforced. |
rate_limit_exceeded | 429 | Rate limit exceeded on any sliding window (per-second, per-minute, per-hour, or per-day). Check `X-RateLimit-*` headers for retry timing. |
engine_error | 502 | The upstream search engine returned an error (timeout, DNS failure, invalid response). Credits are automatically refunded. |
engine_blocked | 429 | The engine detected bot traffic (CAPTCHA, anomaly page, 403/429). Triggers fallback engines or proxy rotation. |
engine_timeout | 504 | The search engine did not respond within the timeout window. Credits are automatically refunded. |
engine_parse_error | 502 | The engine returned a response but the HTML could not be parsed. Credits are automatically refunded. |
not_found | 404 | The requested resource (endpoint, key, or entity) does not exist. |
cache_error | 500 | An error occurred with the cache subsystem (Redis connection failure, serialization error). The request may still succeed without caching. |
llm_error | 502 | The LLM provider returned an error (timeout, rate limit, invalid response). Credits are automatically refunded. |
scrape_error | 502 | The scraping engine failed to extract content from the URL (timeout, DNS error, connection refused). Credits are automatically refunded. |
license_error | 403 | License validation failed or the requested feature is not available on your license tier. |
config_error | 500 | A server configuration error occurred. This is a server-side issue — contact support with the request_id. |
Jiro automatically refunds credits when an error occurs after credits have been deducted from your balance. This ensures you are never charged for failed requests.
Automatic refunds apply to:
- ENGINE_ERROR (502) — the upstream engine returned an error
- ENGINE_UNAVAILABLE (503) — the engine circuit breaker is open
- Any server-side error (500) that occurs after credit deduction
How refunds work:
1. Credits are deducted before the upstream request is made
2. If the upstream call fails, a refund transaction is created immediately
3. Your balance is updated in real-time
4. The refund appears in your credit history as a REFUND_* transaction type
No refunds for:
- INVALID_API_KEY (401) — no credits are deducted for auth failures
- USER_RATE_LIMITED (429) — no credits are deducted for rate-limited requests
- INSUFFICIENT_CREDITS (402) — the request is rejected before any deduction
- Successful requests — credits are consumed as expected