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://api.getchatads.com/v1/chatads/messages' \
  -H 'x-api-key: cak_your_api_key' \
  -H 'Content-Type: application/json' \
  -d '{"message": "test"}'
Checklist:
  • Header name is x-api-key
  • No “Bearer” prefix—just the key value
  • Key is not empty or whitespace
Cause: API key is invalid or doesn’t exist.Solution:
  1. Verify your key starts with cak_
  2. Check for typos in the API key
  3. Generate a new key at getchatads.com/settings/api-keys
Common causes:
  • Typo in the API key
  • Key was regenerated (old key no longer valid)
  • Using a key from a different environment
Cause: The API key has been explicitly disabled.Solution: Re-enable the key in the dashboard or generate a new one at 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",
    "message": "Message exceeds maximum length of 5000 characters"
  }
}
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": "BLOCKED_KEYWORD",
    "message": "Content blocked by keyword filter"
  }
}
Solution:
  1. Review blocked keywords at 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": "COUNTRY_NOT_ALLOWED",
    "message": "Country not allowed"
  }
}
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_LIMIT_EXCEEDED",
    "message": "Daily request limit exceeded"
  }
}
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_LIMIT_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_LIMIT_EXCEEDED",
    "message": "Monthly request limit exceeded"
  }
}
Solution:
  • Wait until the 1st of next month
  • Upgrade to a paid plan (unlimited monthly)

Server Errors

Cause: Unexpected server error.Solution:
  1. Retry the request after a short delay
  2. If persistent, check chatads.statuspage.io for outages
  3. Contact chris@getchatads.com with your request_id
if (response.error?.code === 'INTERNAL_ERROR') {
  console.error('Request ID for support:', response.meta?.request_id);
}
Cause: Rate limiting backend temporarily unavailable.Solution:
  • Retry after a few seconds with exponential backoff
  • This is rare and typically resolves quickly
  • Check chatads.statuspage.io if persistent

Understanding the Response Status

The data.status field indicates the outcome of the request:
StatusMeaningWhen This Occurs
"filled"All requested offers were filledreturned == requested
"partial_fill"Some offers filled (multi-offer mode)0 < returned < requested
"no_offers_found"No offers availablereturned == 0 (no keywords detected, no links found, or filtered)
"internal_error"Service failureTimeout, service unavailable, or unexpected error
Example response with no offers:
{
  "data": {
    "status": "no_offers_found",
    "offers": [],
    "requested": 1,
    "returned": 0
  },
  "error": null
}
The offers array only contains offers with URLs. If the array is empty, check the status field to understand why no offers were returned.

Common Integration Issues

No Matches Found

returned: 0 in response

Symptoms: API returns successfully but data.returned is 0.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 intent threshold
    // status will be no_offers_found
    {
      "data": {
        "status": "no_offers_found",
        "offers": [],
        "returned": 0
      }
    }
    
  3. No affiliate available - Product identified but no affiliate link exists
  4. Message too short - After sanitization (removing PII, URLs, blocked keywords), no words remain
    // Example: "user@email.com" becomes empty after sanitization
    // Single-word product names are supported
    
Solutions:
  • Use more specific product queries
  • Check the status field for specifics

Slow Response Times

API latency exceeds expectations

Expected latencies:
ConfigurationTypical Latency
fast extraction + fast quality100-150ms
thorough extraction + fast quality200-300ms
thorough extraction + standard quality~1.4s
thorough extraction + best quality~2.5s
If consistently slow:
  1. Use fast quality mode
    {
      "message": "...",
      "quality": "fast"
    }
    
  2. Check network latency - API is hosted on Fly.io (global regions)
  3. 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("...");

// Check error is null AND data exists
if (response.error === null && response.data?.returned > 0) {
  // Use the affiliate link
  const offer = response.data.offers[0];
}
Python SDK:
# Use attribute access, not dictionary access
response = client.analyze_message(message="...")

if response.error is None and response.data.returned > 0:
    print(response.data.offers[0].url)  # Correct
Common issues:
  • Not handling data: null when error is present
  • Not checking returned > 0 before accessing offers
  • Using wrong import path

Debug Checklist

When troubleshooting, work through this checklist:
1

Verify API key

# Test with curl
curl -X POST 'https://api.getchatads.com/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 error field first:
if (response.error !== null) {
  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

Check your request parameters and timing:
console.log('Request ID:', response.meta?.request_id);
console.log('Timing:', response.meta?.timing_ms);
console.log('Country:', response.meta?.country);

Getting Help