Magic Link IP Limit Exceeded
magic_link_ip_limit_exceeded429
Too many magic link requests from your IP. Wait 1 hour before requesting another.
What this means
We received too many magic link sign-in requests from the same IP address in a short window. The retry_after field is 3600 (one hour) by contract. This limit exists to protect users from email-bombing attacks — a hostile actor flooding magic links to wear out an inbox or burn through delivery quotas.
When you'll see this
- A user clicked "send magic link" repeatedly when the first link arrived slowly.
- An automated test or QA flow is requesting magic links in a loop from the same IP.
- A shared corporate or campus network is producing many legitimate magic-link requests from one egress IP.
- A buggy client retried the magic-link endpoint on a different error.
Learn more about how this works
Magic link endpoints have stricter rate limits than the general API surface — because the side effect is email delivery (cost, reputation, abuse vector), not just a calculation. We enforce limits at two boundaries: per IP (this error) and per email address (magic_link_email_limit_exceeded). Both have a 1-hour cooldown.
In practice: a real user hitting this is rare. When it happens, the right response is to tell them clearly what's going on rather than silently failing. "Too many requests — please wait an hour" is a better UX than a generic "something went wrong."
Example response
{
"success": false,
"error": "magic_link_ip_limit_exceeded",
"message": "Too many magic link requests from this IP.",
"details": [],
"retry_after": 3600,
"doc_url": "https://docs.asterwise.com/reference/errors/magic_link_ip_limit_exceeded",
"request_id": "req_01HXYZABCDEFGH",
"timestamp": "2026-05-25T12:34:56Z"
}
- Wait 60 minutes. The IP-level limit will clear automatically.
- If a different user on your network needs to sign in immediately, have them switch to a mobile network or different IP.
- If this is happening during automated testing, mock the magic-link endpoint in test environments instead of calling it for real.
Surface a clear, time-bounded error message to the user. Don't let them keep clicking "resend" when you know the call will keep failing.
Python:
Production handler
- Python
- TypeScript
import httpx
def request_magic_link(email, base_url, headers):
response = httpx.post(
f"{base_url}/v1/auth/magic-link",
headers=headers,
json={"email": email},
timeout=10,
)
if response.status_code == 429:
body = response.json()
if body.get("error") == "magic_link_ip_limit_exceeded":
wait_minutes = (body.get("retry_after", 3600)) // 60
return {
"ok": False,
"user_message": (
f"Too many sign-in requests from your network. "
f"Please try again in {wait_minutes} minutes."
),
}
response.raise_for_status()
return {"ok": True}
async function requestMagicLink(email: string, baseUrl: string, headers: HeadersInit) {
const response = await fetch(`${baseUrl}/v1/auth/magic-link`, {
method: "POST",
headers,
body: JSON.stringify({ email }),
});
if (response.status === 429) {
const body = await response.json();
if (body.error === "magic_link_ip_limit_exceeded") {
const waitMinutes = Math.floor((body.retry_after ?? 3600) / 60);
return {
ok: false,
userMessage:
`Too many sign-in requests from your network. ` +
`Please try again in ${waitMinutes} minutes.`,
};
}
}
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return { ok: true };
}
Avoid this error by
- Disable the "send magic link" button in your UI for at least 60 seconds after a successful send. Most users click "resend" because the first email feels slow, not because it actually failed.
- Tell users to check their spam folder before they retry. The most common cause of "I didn't get the email" is a misclassified spam mark, not a delivery failure.
- In QA and automated testing, mock the magic-link endpoint. Never hit the real magic-link endpoint from CI.
- If you have many users behind one corporate IP, consider an SSO flow instead of magic links — it scales better for shared egress.