Skip to main content

Error Code Reference

Every ChatAds error includes a code, message, and optional details. Here’s how to resolve each one:

Authentication Errors

Cause: No API key provided in the request.Solution:
# Add the X-API-Key header
curl -X POST 'https://chatads--chatads-api-fastapiserver-serve.modal.run/v1/chatads/messages' \
  -H 'X-API-Key: cak_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{"message": "test"}'
Checklist:
  • Header name is exactly X-API-Key (case-sensitive)
  • No “Bearer” prefix—just the key value
  • Key is not empty or whitespace
Cause: API key is invalid or disabled.Solution:
  1. Verify your key starts with cak_
  2. Check if the key was revoked at app.getchatads.com/settings/api-keys
  3. Generate a new key if needed
Common causes:
  • Typo in the API key
  • Key was regenerated (old key no longer valid)
  • Team account suspended
Cause: The API key has been explicitly disabled.Solution: Re-enable the key in the dashboard or generate a new one at app.getchatads.com/settings/api-keys.

Input Validation Errors

Cause: Request body is missing or malformed.Solution:
// Correct format
{
  "message": "What's a good yoga mat?"
}

// NOT this (empty message)
{
  "message": ""
}

// NOT this (missing message)
{
  "country": "US"
}
Checklist:
  • Content-Type: application/json header is set
  • Request body is valid JSON
  • message field is present and non-empty
Cause: Message exceeds 5000 characters.Response details:
{
  "error": {
    "code": "MESSAGE_TOO_LONG",
    "details": {
      "max_length": 5000,
      "actual_length": 6234
    }
  }
}
Solution: Truncate or summarize the message. For long conversations, send only the relevant portion:
const message = userMessage.slice(0, 5000);

Content Restriction Errors

Cause: Message contains a keyword blocked by your team’s rules.Response details:
{
  "error": {
    "code": "CONTENT_BLOCKED",
    "details": {
      "keyword": "competitor-product",
      "reason": "Product not in our catalog"
    }
  }
}
Solution:
  1. Review blocked keywords at app.getchatads.com/settings/rules
  2. Remove the rule if blocking was unintended
  3. This request does NOT count against your quota
Cause: Request originated from a disallowed country.Response details:
{
  "error": {
    "code": "GEO_BLOCKED",
    "details": {
      "country": "CN",
      "allowed_countries": ["US", "CA", "GB"],
      "ip": "203.0.113.1"
    }
  }
}
Solution:
  1. Review geo-restrictions in your team settings
  2. Pass the correct country parameter to override IP detection
  3. This request does NOT count against your quota

Rate Limit Errors

Cause: Daily request limit reached.Response details:
{
  "error": {
    "code": "DAILY_QUOTA_EXCEEDED",
    "details": {
      "daily_usage": 101,
      "daily_limit": 100,
      "plan": "free"
    }
  }
}
Solution:
  • Wait until midnight UTC for reset
  • Upgrade your plan for higher limits
  • Check Retry-After header for seconds until reset
if (response.error?.code === 'DAILY_QUOTA_EXCEEDED') {
  const retryAfter = response.headers.get('Retry-After');
  console.log(`Retry after ${retryAfter} seconds`);
}
Cause: Monthly request limit reached (free tier only).Response details:
{
  "error": {
    "code": "MONTHLY_QUOTA_EXCEEDED",
    "details": {
      "monthly_usage": 101,
      "monthly_cap": 100,
      "plan": "free"
    }
  }
}
Solution:
  • Wait until the 1st of next month
  • Upgrade to a paid plan (unlimited monthly)
Cause: Too many requests per minute.Solution: Implement exponential backoff:
async function withRetry(fn: () => Promise<any>, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const result = await fn();

    if (result.success) return result;

    if (result.error?.code === 'RATE_LIMIT_EXCEEDED') {
      const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
      await new Promise(r => setTimeout(r, delay));
      continue;
    }

    throw new Error(result.error?.message);
  }
}

Server Errors

Cause: Unexpected server error.Solution:
  1. Retry the request after a short delay
  2. If persistent, check status.getchatads.com for outages
  3. Contact support@getchatads.com with your request_id
if (response.error?.code === 'INTERNAL_ERROR') {
  console.error('Request ID for support:', response.meta?.request_id);
}
Cause: Service temporarily unavailable.Solution:
  • Retry after 30-60 seconds
  • Check status page for maintenance windows
  • This is typically brief (< 5 minutes)
Cause: Rate limiting backend temporarily unavailable.Solution: This is rare and usually resolves within seconds. Retry with backoff.

Common Integration Issues

No Matches Found

matched: false in response

Symptoms: API returns successfully but data.matched is false.Possible causes:
  1. No product detected - The message doesn’t contain a clear product reference
    // This won't match
    { "message": "Hello, how are you?" }
    
    // This will match
    { "message": "What's a good yoga mat for beginners?" }
    
  2. Intent score too low - Query filtered by min_intent
    // Check if intent was filtered
    {
      "data": {
        "matched": false,
        "reason": "Intent score below threshold",
        "min_intent_required": "medium"
      }
    }
    
  3. No affiliate available - Product identified but no affiliate link exists
Solutions:
  • Lower min_intent (try "any" for testing)
  • Use more specific product queries
  • Check the reason field for specifics

Slow Response Times

API latency exceeds expectations

Expected latencies:
ConfigurationTypical Latency
fast + speed50-100ms
balanced + coverage150-300ms
thorough + coverage300-500ms
If consistently slow:
  1. Check your configuration
    {
      "message": "...",
      "message_analysis": "fast",
      "fill_priority": "speed"
    }
    
  2. Use skip_message_analysis for known products
    {
      "message": "wireless running headphones",
      "skip_message_analysis": true
    }
    
  3. Check network latency - API is hosted on Modal (US regions)
  4. Cache responses - Same queries return same results

SDK Issues

SDK not working as expected

TypeScript SDK:
// Ensure you're awaiting the response
const response = await client.analyzeMessage({ message: "..." });

// Check both success AND data
if (response.success && response.data?.matched) {
  // Use the affiliate link
}
Python SDK:
# Use attribute access, not dictionary access
response = client.analyze_message(message="...")

if response.success and response.data.matched:
    print(response.data.ad.link)  # Correct
    # print(response.data['ad']['link'])  # Wrong
Common issues:
  • Not handling data: null when success: false
  • Not checking matched before accessing ad
  • Using wrong import path

Debug Checklist

When troubleshooting, work through this checklist:
1

Verify API key

# Test with curl
curl -X POST 'https://chatads--chatads-api-fastapiserver-serve.modal.run/v1/chatads/messages' \
  -H 'X-API-Key: YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"message": "best yoga mat"}'
2

Check response structure

Always check success field first:
if (!response.success) {
  console.error('Error:', response.error?.code, response.error?.message);
  return;
}
3

Log the request_id

Every response includes a unique ID for debugging:
console.log('Request ID:', response.meta?.request_id);
Include this when contacting support.
4

Check usage

Verify you haven’t hit rate limits:
console.log('Usage:', response.meta?.usage);
5

Review configuration

Ensure parameters match your expectations:
console.log('Analysis used:', response.meta?.message_analysis_used);
console.log('Fill priority:', response.meta?.fill_priority_used);
console.log('Min intent:', response.meta?.min_intent_used);

Getting Help