Troubleshooting
Common issues and solutions for DeepMod integration. This guide helps you quickly identify and resolve problems with API integration, webhook handling, and content moderation.
API Issues
Authentication Problems
401 - Authentication Required
Your API token is missing, invalid, or malformed.
Symptoms:
{
"errors": [
{
"code": "E_UNAUTHORIZED_ACCESS",
"status": 401,
"message": "Unauthorized access"
}
]
}
Solutions:
-
Verify your API token is correctly set in the
Authorizationheader -
Ensure the token format is
Bearer YOUR_API_TOKEN -
Check that your token hasn't been compromised or rotated
-
Confirm you're using the correct token for your organization
Example Fix:
// ❌ Wrong
headers: { 'Authorization': 'YOUR_API_TOKEN' }
// ✅ Correct
headers: { 'Authorization': 'Bearer YOUR_API_TOKEN' }
403 - Insufficient Permissions
Your API token is valid but lacks necessary permissions.
Symptoms:
{
"errors": [
{
"code": "E_FORBIDDEN",
"status": 403,
"message": "Forbidden"
}
]
}
Solutions:
-
Verify your organization has an active subscription
-
Check that your subscription hasn't expired
-
Ensure you haven't exceeded your plan limits
-
Contact support if permissions appear incorrect
Request Validation Errors
422 - Validation Failed
Request body or parameters don't meet API requirements.
Missing Required Fields:
{
"code": "VALIDATION_ERROR",
"status": 422,
"message": "Validation failed",
"errors": [
{
"field": "policyId",
"message": "The policyId field is required"
}
]
}
Solutions:
-
Ensure
policyIdandcontentare included in all moderation requests -
Verify
policyIdreferences an active policy -
Check that content is a non-empty string
-
Validate metadata structure (must be valid JSON object)
Invalid Policy Reference:
-
Policy ID doesn't exist or belongs to different organization
-
Policy is inactive
-
Using numeric ID when friendly identifier expected (or vice versa)
Content Issues:
-
Empty or null content
-
Content exceeds maximum size limits
-
Invalid content encoding
404 - Resource Not Found
The requested resource doesn't exist.
Symptoms:
{
"errors": [
{
"code": "E_NOT_FOUND",
"status": 404,
"message": "Not found"
}
]
}
Common Causes:
-
Policy URI is incorrect or policy was deleted
-
Resource belongs to a different organization
-
Typographical error in the URI
Rate Limiting and Usage Limits
429 - Too Many Requests
You're exceeding API rate limits. These are two distinct types of limits:
API Rate Limits (requests per minute):
When you exceed the per-minute request limit:
{
"errors": [
{
"code": "E_RATE_LIMIT",
"status": 429,
"message": "Too many requests"
}
]
}
Response Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 45
Retry-After: 45
Solutions:
-
Implement exponential backoff retry logic
-
Reduce request frequency
-
Consider batching requests where possible
-
Upgrade to higher plan for increased limits
Monthly Credit Limits:
When you exceed your monthly moderation credits:
{
"errors": [
{
"code": "E_USAGE_LIMIT_REACHED",
"status": 429,
"message": "Your organization has reached its monthly credit limit"
}
]
}
Solutions:
-
Check your current usage in Organization Settings > Usage
-
Wait for your billing period to reset, or
-
Upgrade to a higher plan for more credits
-
Review your policies for optimization opportunities (fewer rules = fewer credits per moderation)
Example Retry Implementation:
async function submitWithRetry(policyUri, content, metadata, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('https://api.deepmod.ai/v1/moderation/run', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ policyUri, content, metadata }),
});
if (response.status === 429) {
// Check for Retry-After header
const retryAfter = response.headers.get('Retry-After');
const delay = retryAfter
? parseInt(retryAfter, 10) * 1000
: Math.min(1000 * Math.pow(2, attempt), 10000);
if (attempt === maxRetries) {
throw new Error('Rate limit exceeded after max retries');
}
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.errors?.[0]?.message || 'Request failed');
}
return await response.json();
} catch (error) {
if (attempt === maxRetries) throw error;
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
Content Processing Errors
400 - Content Too Large
Content exceeds token limits for AI processing.
Symptoms:
{
"errors": [
{
"code": "E_BAD_REQUEST",
"status": 400,
"message": "Content is too long for moderation. Please reduce the content size."
}
]
}
Solutions:
-
Reduce content length (DeepMod automatically chunks, but extremely large content may still exceed limits)
-
Remove unnecessary boilerplate text before submission
-
Split very large documents into logical sections
AI Service Errors
500 - AI Model Unavailable
Temporary issues with underlying AI services.
Symptoms:
{
"errors": [
{
"code": "E_INTERNAL_SERVER_ERROR",
"status": 500,
"message": "AI model is temporarily unavailable. Please try again later."
}
]
}
Common Messages:
-
"AI model is temporarily unavailable. Please try again later."
-
"Received invalid response from AI service. Please try again."
-
"AI service error. Please try again later."
Solutions:
-
Implement retry logic with exponential backoff
-
These are usually temporary - retry after a few seconds
-
Check DeepMod status page for known issues
-
Contact support if errors persist
503 - Service Unavailable
External AI service is temporarily unavailable.
Symptoms:
{
"errors": [
{
"code": "E_SERVICE_UNAVAILABLE",
"status": 503,
"message": "AI service is temporarily unavailable"
}
]
}
Solutions:
-
Wait and retry - this is typically a temporary condition
-
Implement circuit breaker patterns for resilience
-
Check Deep Mod status page for outage information
504 - Request Timeout
The moderation request took too long to process.
Solutions:
-
Reduce content length if possible
-
Simplify policy (fewer rules)
-
Retry the request
Webhook Issues
Webhook Delivery Problems
Moderation completes but no webhook arrives.
Diagnostic Steps:
-
Verify Webhook URL:
-
Confirm URL is publicly accessible
-
Test endpoint manually with a simple POST request
-
Check for HTTPS requirement
-
-
Check Webhook Configuration:
-
Organization must have valid webhook URL configured
-
Webhook URL cannot be localhost or private IP
-
URL must respond with 2xx status code
-
-
Review Server Logs:
-
Look for incoming POST requests to your webhook endpoint
-
Check for 4xx/5xx errors in your responses
-
Verify request handling is working correctly
-
Common Issues:
-
Webhook URL returns non-2xx status codes
-
Endpoint times out (must respond quickly)
-
Server rejects requests due to missing headers
Webhook Event Types
Deep Mod sends different webhook events depending on the operation:
|
Event Type |
Description |
|---|---|
|
|
Single moderation completed successfully |
|
|
Batch moderation completed (all policies processed) |
|
|
Moderation failed due to an error |
|
|
Revision mode completed with rewritten content |
Example Webhook Payload (Moderation.Completed):
{
"id": "job_abc123",
"type": "Moderation.Completed",
"data": {
"moderation": {
"result": "SUCCESS",
"confidence": 0.95,
"evaluations": [...]
},
"metadata": {},
"tags": []
}
}
Webhook Verification Issues
Signature Verification Failing
Webhooks arrive but signature verification fails.
Important: The signature is sent in the x-deepmod-signature header.
Troubleshooting Steps:
-
Check Client Secret:
-
Verify you're using the correct client secret from Organization Settings
-
Ensure secret hasn't been accidentally modified
-
-
Verify Signature Calculation:
const crypto = require('crypto'); function verifyWebhookSignature(rawBody, signature, clientSecret) { // rawBody must be the exact request body string, not parsed JSON const expectedSignature = crypto .createHmac('sha256', clientSecret) .update(rawBody) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) ); } // Express.js example app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-deepmod-signature']; const rawBody = req.body.toString(); if (!verifyWebhookSignature(rawBody, signature, CLIENT_SECRET)) { return res.status(401).send('Invalid signature'); } const payload = JSON.parse(rawBody); // Process webhook... res.status(200).send('OK'); }); -
Raw Body Required:
-
Use raw request body, not parsed JSON
-
Signature is calculated on the exact bytes received
-
Many frameworks parse JSON automatically - ensure you capture raw body first
-
Webhook Timeouts
Webhook Processing Takes Too Long
DeepMod expects webhooks to respond quickly.
Solutions:
-
Respond with 200 status immediately upon receipt
-
Process webhook payload asynchronously
-
Implement idempotent handling to avoid duplicate processing
Example Pattern:
app.post('/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
// Verify signature first
const signature = req.headers['x-deepmod-signature'];
const rawBody = req.body.toString();
if (!verifyWebhookSignature(rawBody, signature, CLIENT_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Respond immediately
res.status(200).send('OK');
// Process asynchronously
const payload = JSON.parse(rawBody);
processWebhookAsync(payload);
});
async function processWebhookAsync(payload) {
// Idempotency check using payload.id
if (await isAlreadyProcessed(payload.id)) {
return;
}
// Your webhook processing logic here
await markAsProcessed(payload.id);
}
Policy and Configuration Issues
Policy Activation Problems
Cannot Activate Policy
Policy activation fails despite appearing configured.
Common Causes:
-
No webhook URL configured
-
Webhook URL unreachable or returning errors
-
Policy has no rule groups or rules
-
All rules are invalid or empty
Solutions:
-
Configure valid webhook URL in Organization Settings
-
Test webhook endpoint manually
-
Ensure policy has at least one rule group with valid rules
-
Review rule validation errors in dashboard
Unexpected Moderation Results
All Content Being Flagged/Approved
Results don't match expectations.
Diagnostic Steps:
-
Review Rule Configuration:
-
Check rule content and descriptions
-
Verify rule groups are properly configured
-
Test rules individually using the policy tester
-
-
Check Confidence Threshold:
-
Lower thresholds = more sensitive (more ambiguous results)
-
Higher thresholds = less sensitive (more definitive results)
-
Optimal range is typically 0.6-0.8
-
-
Validate Test Content:
-
Use diverse test cases
-
Include clear violations and clear approvals
-
Test edge cases and ambiguous content
-
Batch Moderation Issues
Partial Batch Failures
Some policies in a batch succeed while others fail.
Symptoms:
The Moderation.BatchCompleted webhook includes results for each policy:
{
"type": "Moderation.BatchCompleted",
"data": {
"batch": {
"result": "FAILURE",
"moderation": [
{ "result": "SUCCESS", "policyUri": "policy-1" },
{ "result": "FAILURE", "policyUri": "policy-2", "error": "Policy not found" }
]
}
}
}
Batch Result Priority:
-
FAILURE(highest) - Any policy failed -
AMBIGUOUS- Any policy returned ambiguous, none failed -
SUCCESS- All policies succeeded
Solutions:
-
Check each individual result in the batch response
-
Verify all policy URIs exist and are active
-
Handle partial failures in your integration logic
Performance Issues
Slow Response Times
Moderation Taking Too Long
Processing time exceeds expected duration.
Factors Affecting Speed:
-
Content length (longer content takes more time)
-
Policy complexity (more rules = longer processing)
-
Current system load
-
Network latency
Optimization Strategies:
-
Remove unnecessary rules from policies
-
Use more specific, focused rules
-
Clean content before submission (remove boilerplate)
-
Implement proper error handling and timeouts
High Ambiguous Results
Too Many Moderation Results Require Review
Excessive ambiguous outcomes impact workflow efficiency.
Solutions:
-
Adjust Confidence Threshold:
-
Start with 0.7 and adjust based on results
-
Lower for more definitive decisions (may increase false positives/negatives)
-
Higher for more conservative approach (more manual review)
-
-
Improve Rule Clarity:
-
Use specific, concrete rule descriptions
-
Avoid vague or overly broad rules
-
Include clear examples of violations
-
-
Policy Structure:
-
Group related rules logically
-
Ensure rules don't conflict with each other
-
Test rule combinations thoroughly
-
Error Response Format
All API errors follow this structure:
{
"errors": [
{
"code": "E_ERROR_CODE",
"status": 400,
"message": "Human-readable error message",
"field": "fieldName" // Only present for validation errors
}
]
}
Handling Multiple Errors:
async function handleApiResponse(response) {
if (!response.ok) {
const errorData = await response.json();
for (const error of errorData.errors || []) {
console.error(`[${error.code}] ${error.message}`);
if (error.field) {
console.error(` Field: ${error.field}`);
}
}
throw new Error(errorData.errors?.[0]?.message || 'Unknown error');
}
return response.json();
}
Getting Help
Before Contacting Support
Information to Gather:
-
API Issues:
-
Full error response (including
codefield) -
HTTP status code
-
Request details (endpoint, headers, body)
-
API token (last 4 characters only)
-
Timestamp of the issue
-
Any rate limit headers received
-
-
Webhook Issues:
-
Webhook URL being used
-
Expected vs. actual behavior
-
Server logs showing incoming requests
-
Signature verification implementation
-
The
x-deepmod-signatureheader value received
-
-
Moderation Issues:
-
Policy ID and name
-
Sample content that's not working as expected
-
Expected vs. actual results
-
Confidence threshold settings
-
Still having issues? Contact support with the debug information above for faster resolution.