Skip to content
5 min read

Errors & Limits

Common errors and how to handle them. All APIs return structured error responses.

HTTP Status Codes

Status Meaning Typical Cause Retry?
200 OK Request succeeded No
201 Created Resource created No
400 Bad Request Invalid field/format No — fix and retry
401 Unauthorized Missing/invalid auth token Maybe — check token expiry
403 Forbidden Permission denied No — check organization/role
404 Not Found Resource doesn't exist No
429 Too Many Requests Rate limit exceeded Yes — wait Retry-After seconds
500 Server Error Server error Yes — after 5+ seconds
502 Bad Gateway Temporarily unavailable Yes — after 5+ seconds
503 Service Unavailable Server maintenance Yes — check status page

Error Response Format

Most errors return a JSON body with details:

{
  "message": "Human-readable error message",
  "error": "machine_error_code"
}

Example:

{
  "message": "The email field is required.",
  "errors": {
    "email": ["The email field is required."]
  }
}

Common Errors

401 Unauthorized

Cause: Missing, invalid, or expired authentication token.

Fix:

  • Ensure Authorization: Bearer <token> header is present
  • Re-login if the token expired: POST /api/agent/login
  • For OTP API, check X-Wallin-OTP-Key: <key> header

403 Forbidden

Cause: You don't have permission to access this resource (wrong organization, role, etc.).

Fix:

  • Verify you belong to the organization (check X-Organization-Id header)
  • Ensure your role allows the action (e.g., agents can't create campaigns)
  • Ask an admin to grant permission if needed

429 Too Many Requests

Cause: You exceeded the rate limit.

Response includes Retry-After header:

Retry-After: 60

Fix:

  • Wait the specified seconds before retrying
  • Implement exponential backoff: 1s, 2s, 4s, 8s, etc.
  • For OTP API, check daily/monthly quota at /otp-applications

Rate Limits:

Endpoint Limit Reset
Agent API (all) 100 requests/minute Per minute
OTP Send 5 per phone/hour, 20 per IP/hour Hourly
OTP Verify 3 attempts per code Per code
WhatsApp Send Varies by Meta WABA quality Varies

500 Internal Server Error

Cause: Server error (rare).

Fix:

Validation Errors

When a request has invalid fields, you get a 400 Bad Request with details:

{
  "message": "The given data was invalid.",
  "errors": {
    "phone_number": ["Phone number must be in E.164 format (e.g. +201001234567)."],
    "code": ["The code field is required."]
  }
}

Fix:

  • Correct the field values and resubmit
  • Check the error message for the exact requirement

OTP-Specific Errors

Send Error: rate_limit_exceeded

Max 5 OTPs per phone number per hour.

{
  "message": "Maximum 5 OTPs per hour per phone number",
  "error": "rate_limit_exceeded",
  "retry_after": 3600
}

Fix: Wait 1 hour or use a different phone number.

Send Error: quota_exceeded

Your organization hit its monthly OTP limit.

{
  "error": "quota_exceeded"
}

Fix: Upgrade your plan at /organizations/settings → Billing.

Verify Error: expired

The OTP code expired (default 5 minutes).

{
  "data": {
    "verified": false,
    "error": "expired"
  }
}

Fix: Call /resend to issue a new code.

Verify Error: max_attempts_exceeded

User exceeded the max wrong guesses (default 3).

{
  "data": {
    "verified": false,
    "error": "max_attempts_exceeded",
    "attempts_remaining": 0
  }
}

Fix: Call /resend to issue a new code (resets attempts).

Verify Error: already_verified

The code was already used.

{
  "data": {
    "verified": false,
    "error": "already_verified"
  }
}

Fix: The code is no longer valid; a new OTP must be sent.

WhatsApp-Specific Errors

Send Error: Template Rejected

Template is not approved by Meta.

{
  "error": "Failed to send message"
}

Fix:

  1. Check template status at /templates
  2. If rejected, review Meta's rejection reason
  3. Resubmit with corrections or use a different template

Send Error: Window Closed (WhatsApp)

Customer hasn't messaged in 24 hours; free-form sends are blocked.

{
  "error": "Failed to send message"
}

Fix:

  • Wait for the customer to message you
  • Use a template with MARKETING or OTP category (if your WABA supports it)
  • Check window_state in conversation details

Send Error: Contact Not Found

Phone number is not connected to the channel.

{
  "error": "Failed to send message"
}

Fix:

  • Verify the phone number format (E.164, e.g., +201001234567)
  • Ensure the contact has WhatsApp/Instagram/Messenger connected
  • Check the business account is correct

Rate Limiting Strategy

Best practices for handling rate limits:

  1. Use exponential backoff:

    retry_after = min(retry_after * 2, 300)  // Cap at 5 minutes
    
  2. Read Retry-After header:

    const retryAfter = response.headers['retry-after'];
    setTimeout(() => retry(request), retryAfter * 1000);
    
  3. Batch requests:

    • Group API calls and make them in parallel (up to rate limit)
    • Avoid rapid sequential requests
  4. Monitor quota:

    • Check OTP monthly usage at /otp-applications
    • Check message usage at /organizations/settings → Billing
    • Upgrade proactively before hitting limits

Plan Message Limits

Plan Messages/Month OTP Requests/Month
Free 1,000 100
Starter 10,000 5,000
Professional 100,000 50,000
Enterprise Unlimited Unlimited

Message count includes:

  • Broadcast messages sent
  • Agent messages sent
  • OTP messages sent

Hitting the limit blocks further sends until next month or plan upgrade.

Debugging Tips

  1. Log all responses: Keep full request/response logs for troubleshooting
  2. Check organization context: Ensure X-Organization-Id is correct
  3. Verify token freshness: Re-login if requests start failing with 401
  4. Test in sandbox: Use WHATSAPP_SIMULATE_API=true locally before production
  5. Monitor Meta status: WhatsApp outages affect sends; check https://status.meta.com

Support

For persistent errors:

  1. Collect the full request and response (including headers)
  2. Note the timestamp and endpoint
  3. Contact support@wallin.example with details
Was this page helpful?

See Wallin on your own channels.

Book a walkthrough — we'll connect a test account and show you the inbox, broadcasts, and automation live.