Skip to content

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 /thing and POST /thing are 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-After and 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 2xx on 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.
  • 502 on 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.
  • 503 on 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.