When your account's sending reputation degrades (high bounce or complaint rate, or a sudden volume spike), Zyphr throttles or freezes sending to protect the shared IP pool. These states apply only to send-capable endpoints — read, billing, and deliverability endpoints stay available so you can diagnose and recover.
Code
HTTP Status
Description
Resolution
account_frozen
403
Sending is frozen for the account (reputation). The error message carries the specific reason.
Stop sending to invalid addresses, clean your recipient list, then contact support@zyphr.dev to unfreeze.
account_throttled
429
A percentage of sends are rejected while reputation recovers. The error message carries the reason.
Back off and retry; reduce bounce/complaint rates. Throttling lifts automatically once rates return to acceptable levels.
Every authenticated response includes the current sending state as headers, so you can surface it without a separate call:
X-Account-Sending-Status is one of active, throttled, or frozen. X-Account-Sending-Status-Reason is present only when the status is not active. See API Limits for details.
MFA verification needed. Not an error — the login/verify endpoints return this as a 200 response body flag ({ "data": { "mfa_required": true, "mfa_challenge": { … } } }), not an error status. Branch on the mfa_required field.
Complete the MFA challenge with the returned mfa_challenge.token
otp_invalid
400
OTP code is incorrect
Enter the correct code
otp_expired
400
OTP code has expired
Request a new code
otp_max_attempts
400
Too many failed attempts on this code — it is now locked
Request a new code
invalid_totp
401
TOTP code is incorrect
Enter the current code from the authenticator app
invalid_backup_code
401
Backup code is invalid or already used
Use an unused backup code, or re-verify with TOTP
invalid_mfa
401
MFA challenge is invalid or expired
Restart the MFA challenge
invalid_verification
401
Verification code is incorrect (TOTP re-verification of an active session)
Re-enter the current code
invalid_code
400
Verification code is incorrect (during MFA enrollment)
Re-enter the code from the authenticator app
mfa_not_enabled
400
MFA is not enabled for this account
Enroll in MFA first
mfa_already_enabled
409
MFA is already enabled
No action needed
no_pending_enrollment
400
No MFA enrollment is in progress to verify
Start enrollment before verifying
email_required
400
The account must have an email address to enable MFA
Add an email to the account first
Branch on code, not message
Every error response includes a stable, machine-readable error.code alongside the human-readable error.message. Branch your control flow on error.code (and the HTTP status) — treat message as display-only text that may be reworded or localized at any time.
Returned by the email-OTP (/auth/email-otp/*) and phone-OTP (/auth/phone/*) send/verify endpoints.
Code
HTTP Status
Description
Resolution
email_not_found
400
No account exists for this email (on login send/verify)
Fall back to a registration flow, or prompt the user to sign up
phone_not_found
400
No account exists for this phone number (on login send/verify)
Fall back to a registration flow
email_already_registered
400
Email is already registered (on registration send)
Switch to the login flow
phone_already_registered
400
Phone number is already registered (on registration send)
Switch to the login flow
otp_invalid
400
Verification code is incorrect
Re-enter the code
otp_expired
400
No active code found, or it has expired
Request a new code
otp_max_attempts
400
Code locked after too many failed attempts
Request a new code
invalid_email
400
Email address is malformed
Correct the address
invalid_phone
400
Phone number is not valid E.164
Use E.164 format (e.g. +14155551234)
user_inactive
400
The account is suspended or deleted
Contact support
email_not_configured
503
Email OTP requires a verified sending domain on the project
Verify a domain in Settings → Domains
sms_not_configured
503
Phone OTP requires configured SMS (Twilio) credentials. On the auth-OTP endpoints this is 503; the same code is returned as 400 by the direct SMS-send API (see Configuration Errors).
Configure Twilio in Settings → SMS
sms_send_failed
400
The SMS provider failed to send the code
Retry; if persistent, check the SMS provider configuration
otp_send_rate_limit_exceeded
429
Too many code requests for this identifier
Wait retry_after seconds before requesting another code
otp_verify_rate_limit_exceeded
429
Too many verification attempts for this identifier
Feature or limit requires a plan upgrade. Status is route-dependent — mostly 403 (plan-gated features: webhooks, WaaS, organizations, Muse); 402 on a few paywall paths (e.g. custom domains). Branch on the code, not the status.
Native gaming identity endpoints (POST /v1/auth/game-center, POST /v1/auth/google-play-games) return intentionally opaque errors on any verification failure — the specific control that failed (signature, certificate chain, timestamp, bundle id, token exchange) is never disclosed, to avoid giving an attacker a probing oracle.
Code
HTTP Status
Description
Resolution
invalid_assertion
401
Apple Game Center assertion failed verification (any of: signature, certificate chain, timestamp freshness/replay, or bundle-id binding). Opaque by design.
Most common cause: sending the wrong player id. Send GKLocalPlayer.teamPlayerID (form T:_…) as playerId — this is the id GameKit signs over. gamePlayerID (A:_…) and the deprecated playerID fail even on an otherwise-perfect assertion. Also confirm a fresh assertion (within the ±5-min window) and a bundle id in the app's trusted allow-list.
invalid_auth_code
401
Google Play Games server auth code failed verification (invalid/expired code, token exchange failure, or player lookup failure). Opaque by design.
Send a fresh single-use serverAuthCode from requestServerSideAccess using the game's web/server client id.
provider_not_configured
401
The gaming provider isn't configured/enabled for this application.
Enable and configure the provider under Applications → [App] → OAuth → Native gaming identity.
environment_required
400
The request lacks the environment context needed to resolve provider config.
Ensure the application key resolves to a valid environment.