invalid_request
HTTP 400 · A field, header or query parameter is missing or invalid.
Endpoints: Several
When it happens
Section titled “When it happens”| When | Message (as returned) | Fix (as returned) |
|---|---|---|
POST /v1/signup: challenge or nonce is missing or not a string. |
Body needs "challenge" and "nonce". |
GET /v1/signup/challenge, find a nonce so that sha256(challenge + ':' + nonce) starts with `difficulty` zero bits, then POST both. The Replyz CLI and scripts/signup.mjs do this for you. |
agent_name (signup), name or display_name (inboxes) is not a string (null is allowed). |
"{field}" must be a string. |
Send "{field}" as a JSON string. |
| The same fields are longer than 64 characters after control characters are removed and the value is trimmed. | "{field}" is longer than 64 characters. |
Shorten "{field}". |
POST /v1/inboxes: Idempotency-Key is not 1–255 printable ASCII characters (no spaces). |
Idempotency-Key must be 1–255 printable ASCII characters. |
Use a UUID. |
PATCH /v1/inboxes/{id}: the body has no display_name. |
Nothing to update. |
Send {"display_name": "…"} (or null to clear it). |
Read routes: a query parameter is invalid. The fix names the accepted format (table below). |
Invalid query parameter "{name}". |
Depends on the parameter (table below). |
What to do
Section titled “What to do”- Fix the field or parameter named in
message, as thefixsays. Branch oncode, never on themessagetext.
Query parameters
Section titled “Query parameters”| Parameter | Endpoint | Valid values | Fix (as returned) |
|---|---|---|---|
limit |
GET /v1/inboxes/{id}/messages |
Integer 1–100 (default 20) | “Use an integer from 1 to 100.” |
limit |
GET /v1/inboxes/{id}/wait |
Integer 1–50 (default 10) | “Use an integer from 1 to 50.” |
limit |
GET /v1/events |
Integer 1–100 (default 100) | “Use an integer from 1 to 100.” |
timeout |
GET /v1/inboxes/{id}/wait |
Integer 0–60 (default 25) | “Use an integer from 0 to 60.” |
wait |
GET /v1/events |
Integer 0–60 (default 0) | “Use an integer from 0 to 60.” |
after |
GET /v1/events |
Integer 0–9007199254740991 (default 0) | “Use an integer from 0 to 9007199254740991.” |
unread |
GET /v1/inboxes/{id}/messages |
true/1/yes, false/0/no (any case); empty = false |
“Use true or false.” |
exclude_returned |
GET /v1/inboxes/{id}/wait |
Same as unread |
“Use true or false.” |
since |
GET /v1/inboxes/{id}/messages, GET /v1/inboxes/{id}/wait |
ISO 8601 date or date-time, e.g. 2026-11-06T10:00:00Z; a time without an offset is UTC |
“Use an ISO 8601 time, e.g. 2026-11-06T10:00:00Z (encode ‘+’ as %2B).” |
from |
GET /v1/inboxes/{id}/messages, GET /v1/inboxes/{id}/wait |
At most 200 characters | “Use at most 200 characters.” |
subject |
GET /v1/inboxes/{id}/wait |
At most 200 characters | “Use at most 200 characters.” |
before |
GET /v1/inboxes/{id}/messages |
A message id (msg_…), from next_before |
“Use next_before from the previous page.” |
thread_id |
GET /v1/inboxes/{id}/wait |
A thread id (thr_…) |
“Use a thread id (thr_…).” |
extract |
GET /v1/inboxes/{id}/wait |
otp, link or otp,link (any case). An empty value is invalid |
“Use extract=otp, extract=link or extract=otp,link.” |
include |
GET /v1/messages/{id} |
html, raw or html,raw |
“Use include=html, include=raw or include=html,raw.” |
For suspended and expired accounts, timeout (wait) and wait (events) are validated as for any account; the request then answers at once and never holds.
Example
Section titled “Example”{ "type": "https://docs.replyz.io/errors/invalid_request", "code": "invalid_request", "status": 400, "message": "Body needs \"challenge\" and \"nonce\".", "fix": "GET /v1/signup/challenge, find a nonce so that sha256(challenge + ':' + nonce) starts with `difficulty` zero bits, then POST both. The Replyz CLI and scripts/signup.mjs do this for you.", "docs": "https://docs.replyz.io/errors/invalid_request.md"}All codes: Errors.