When calls fail¶
Most problems are self-serve. Find the status code your sender received below — each one tells you exactly what to fix. Every response also carries a short message explaining the cause.
First check
Glance at status.echorelay.dev. If we've posted an incident, it's us — sit tight. If it's all green, read on.
401 — Unauthorized¶
Your key is missing, wrong, revoked, or expired — the response message says which
(invalid_or_missing_key, key_revoked, key_expired). An unknown project address
returns 401 too, so the same response never reveals whether a project exists.
- Confirm you're sending the project's current key (panel → your project).
- If you rotated the key, update your sender to the new one. (Rotations keep the old key working for a short overlap — but not forever.)
- Check you're using the right kind:
er_live_…for real traffic,er_test_…for tests.
402 — Payment required (test traffic only)¶
Only your test credit pool returns this — it's a paid perk that runs on its own cycle. Top it up by buying a credit pack or moving to a paid plan, or switch to your live key.
Live traffic never gets a 402. If your live credits run out, EchoRelay doesn't reject
your requests — it keeps relaying and eases your project down to the free rate until your
balance is refilled. A top-up restores your full rate (one made in the first minute or so keeps you at full
speed, with no interruption at all).
Full detail: Credits & billing.
403 — Forbidden¶
Your key is valid, but the endpoint has an IP allowlist and your sender's IP isn't on it.
- Add your sender's public (egress) IP to the endpoint's allowlist in the panel.
- Behind a NAT or proxy? Use its outbound IP, not your machine's local one.
404 — Not found¶
You're authenticated, but the address didn't match an active line or endpoint. (An
unauthenticated call never gets here — a missing or wrong key returns 401 first,
so paths can't be probed without a valid key.)
- Check the endpoint exists and is active in the panel.
- Check the method matches —
GET /thingandPOST /thingare different endpoints. - Check the address (project, version, path) exactly matches what the panel shows.
422 — Unprocessable¶
Your request reached the endpoint, but the body failed validation — a required field is missing, or a value didn't match the endpoint's rules.
- The response message names what failed. Compare your payload to the endpoint's attributes in the panel.
- Use Dry run in the panel to test a payload without actually sending it.
429 — Too many requests¶
You've hit your rate limit. The response includes a Retry-After header telling you
how long to wait.
- Spread your calls out, or honour
Retry-Afterand retry. - Need more headroom? Raise your limit — see Rate limits.
Calls accepted, but nothing arrives at your target¶
EchoRelay accepted the call (you got a success back) but delivery to your URL is failing.
- EchoRelay retries automatically with backoff when your target is down or returns a retryable error.
- Open your project's request history in the panel to see each attempt and the response your target gave.
- Persistent failures are held aside for replay — you can retry them from the panel (or via the API/MCP) once your target is healthy again. A retry re-sends the request, so it's billed like a normal send — it costs the same credits the original delivery did. If your balance is too low, the item waits until you top up (see Credits & billing).
- Check your target URL is correct, reachable from the public internet, and returns
a
2xxon success.
Streaming calls behave differently¶
A streaming target (SSE or chunked) is forwarded to your caller live — so a streaming
call returns your target's own status (usually 200) and then the response as it
arrives, not the 202 you'd get from a queued delivery.
- Nothing appears gradually / you only get the response at the end — your client is
buffering. Use an SSE client (e.g. browser
EventSource) or, with curl, disable buffering (curl -N/--no-buffer). EchoRelay forwards each chunk as your target produces it. 502on a streaming call — the stream target couldn't be reached or didn't start responding. Nothing was delivered, so you're not charged for it. Check the target URL is reachable from the public internet and answers with a stream.503on a streaming call — too many streams are open at once right now. It's a brief back-pressure signal, not an outage — wait a moment and retry. (You're not charged for it.)- Streams aren't retried. Unlike queued delivery, a streaming call isn't replayed if it fails — re-send it yourself.
Still stuck?¶
Email [email protected] from your account address. Include your project name and, if you have it, a request id from the request history — it lets us find the exact call fast.