Skip to main content

Troubleshooting

This guide helps you diagnose and resolve common issues with API submissions.

Common Error Scenarios

Authentication Errors

401 Unauthorized

Symptoms: All API requests return 401 status

Possible Causes:

  • Invalid or expired API token
  • Missing Authorization header
  • Incorrect token format

Solutions:

# Test your token
curl -H "Authorization: Bearer YOUR_TOKEN" \
https://your-domain.com/api/test

# Check token format (should be 80 characters)
echo $API_TOKEN | wc -c

Verification Steps:

  1. Confirm API token is exactly 80 characters
  2. Check token hasn't expired (contact admin)
  3. Verify Authorization header format: Bearer <token>
  4. Ensure API user account is active

403 Forbidden

Symptoms: Authentication succeeds but access denied

Possible Causes:

  • API user lacks workflow access permissions
  • Workflow is disabled or archived
  • IP address restrictions

Solutions:

  1. Contact admin to verify workflow permissions
  2. Check if workflow ID exists and is active
  3. Verify your IP is whitelisted (if restrictions apply)

Validation Errors

400 Bad Request - Field Validation

Error Response Example:

{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"field_errors": {
"email": "Invalid email format",
"start_date": "Date must be in future",
"amount": "Value must be greater than 0"
}
}
}

Debugging Steps:

  1. Check each field against form validation rules
  2. Verify data types match expected format
  3. Ensure required fields are present
  4. Validate date formats (ISO 8601: YYYY-MM-DD)
  5. Check numeric ranges and constraints

400 Bad Request - JSON Format

Symptoms: "Invalid JSON" error

Common Issues:

// ❌ Incorrect - trailing comma
{
"name": "John",
"age": 30,
}

// ❌ Incorrect - unescaped quotes
{
"description": "He said "hello""
}

// ✅ Correct
{
"name": "John",
"age": 30,
"description": "He said \"hello\""
}

Validation Tools:

  • Use JSON validators (jsonlint.com)
  • Test with curl or Postman first
  • Enable JSON syntax checking in your IDE

Rate Limiting Issues

429 Too Many Requests

Error Response:

{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"limit_type": "hourly_per_ip",
"retry_after": 3600
}

Solutions:

  1. Implement Exponential Backoff:
import time
import random

def submit_with_retry(data, max_retries=3):
for attempt in range(max_retries):
try:
response = submit_data(data)
return response
except RateLimitError as e:
if attempt == max_retries - 1:
raise

# Exponential backoff with jitter
delay = (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
  1. Monitor Rate Limit Headers:
def check_rate_limits(response):
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
reset_time = int(response.headers.get('X-RateLimit-Reset', 0))

if remaining < 10: # Low remaining requests
wait_time = reset_time - int(time.time())
print(f"Rate limit low. Waiting {wait_time} seconds...")
time.sleep(wait_time)
  1. Batch Operations:
# Instead of individual submissions
for item in items:
submit_single(item) # ❌ May hit rate limits

# Batch multiple items
batches = [items[i:i+10] for i in range(0, len(items), 10)]
for batch in batches:
submit_batch(batch) # ✅ More efficient
time.sleep(1) # Rate limiting delay

Workflow and Form Issues

404 Not Found - Workflow

Symptoms: "Workflow not found" error

Debugging:

  1. Verify workflow ID is correct
  2. Check if workflow is published (not draft)
  3. Confirm API user has access to workflow
  4. Ensure workflow hasn't been archived

Field Mapping Issues

Symptoms: Data not appearing correctly in submissions

Common Problems:

  1. Field Name Mismatch:
// Form has field "firstName" but API sends "first_name"
{
"first_name": "John" // ❌ Won't map
}

// Correct field name
{
"firstName": "John" // ✅ Will map
}
  1. Nested Component Issues:
// For nested components, use dot notation or nested objects
{
"address.street": "123 Main St", // Option 1
"address": { // Option 2
"street": "123 Main St",
"city": "Anytown"
}
}
  1. Array/Multi-value Fields:
// For checkboxes, select multiple, etc.
{
"skills": ["javascript", "python", "sql"], // ✅ Array format
"preferences": {
"email": true,
"sms": false,
"phone": true
}
}

Debugging Tools and Techniques

API Testing Tools

1. cURL Testing

# Basic submission test
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"test_field":"test_value"}' \
https://your-domain.com/api/submissions/workflow/123

# Verbose output for debugging
curl -v -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d @test_data.json \
https://your-domain.com/api/submissions/workflow/123

2. Postman Collection

Create a Postman collection with:

  • Environment variables for API token and base URL
  • Pre-request scripts for authentication
  • Test scripts for response validation
// Pre-request script
pm.request.headers.add({
key: 'Authorization',
value: 'Bearer ' + pm.environment.get('api_token')
});

// Test script
pm.test("Status code is 201", function () {
pm.response.to.have.status(201);
});

pm.test("Response has submission ID", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.submission.id).to.be.a('number');
});

Logging and Monitoring

Application Logging

import logging
import json

# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('api_submissions.log'),
logging.StreamHandler()
]
)

logger = logging.getLogger('api_submission')

def submit_with_logging(data):
logger.info(f"Submitting data: {json.dumps(data, indent=2)}")

try:
response = submit_data(data)
logger.info(f"Submission successful: {response['submission']['id']}")
return response
except Exception as e:
logger.error(f"Submission failed: {str(e)}")
logger.error(f"Request data: {json.dumps(data, indent=2)}")
raise

Response Analysis

def analyze_response(response):
"""Analyze API response for debugging"""
print(f"Status Code: {response.status_code}")
print(f"Headers: {dict(response.headers)}")

if response.status_code >= 400:
print(f"Error Response: {response.text}")
else:
data = response.json()
print(f"Success: Submission ID {data['submission']['id']}")

# Check rate limit headers
if 'X-RateLimit-Remaining' in response.headers:
remaining = response.headers['X-RateLimit-Remaining']
reset_time = response.headers.get('X-RateLimit-Reset', 'Unknown')
print(f"Rate Limit: {remaining} requests remaining, resets at {reset_time}")

Performance Debugging

Request Timing

import time
import requests

def timed_request(url, data, headers):
start_time = time.time()

try:
response = requests.post(url, json=data, headers=headers)
end_time = time.time()

duration = end_time - start_time
print(f"Request completed in {duration:.2f} seconds")

if duration > 5.0: # Slow request threshold
print("⚠️ Slow request detected")
print(f"Data size: {len(str(data))} characters")

return response
except requests.exceptions.Timeout:
print("❌ Request timed out")
raise
except requests.exceptions.ConnectionError:
print("❌ Connection error")
raise

Memory Usage Monitoring

import psutil
import os

def monitor_memory_usage():
process = psutil.Process(os.getpid())
memory_info = process.memory_info()

print(f"Memory usage: {memory_info.rss / 1024 / 1024:.2f} MB")

if memory_info.rss > 500 * 1024 * 1024: # 500MB threshold
print("⚠️ High memory usage detected")

Environment-Specific Issues

Development Environment

Common Issues:

  • Self-signed SSL certificates
  • Local network restrictions
  • Development vs production API endpoints

Solutions:

# For development with self-signed certificates
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

# Disable SSL warnings (development only!)
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# Make request with SSL verification disabled
response = requests.post(url, json=data, headers=headers, verify=False)

Production Environment

Monitoring Checklist:

  • SSL certificate validity
  • Network connectivity
  • DNS resolution
  • Firewall rules
  • Load balancer health
  • API server status

Health Check Script:

import requests
import sys

def health_check():
try:
# Test basic connectivity
response = requests.get(
'https://your-domain.com/api/health',
timeout=10
)

if response.status_code == 200:
print("✅ API server is healthy")
return True
else:
print(f"❌ API server returned {response.status_code}")
return False

except requests.exceptions.RequestException as e:
print(f"❌ Health check failed: {e}")
return False

if __name__ == "__main__":
if not health_check():
sys.exit(1)

Getting Help

Information to Gather

When reporting issues, include:

  1. Request Details:

    • Full API endpoint URL
    • Request headers (excluding sensitive tokens)
    • Request body (sanitized)
    • HTTP method used
  2. Response Information:

    • HTTP status code
    • Response headers
    • Complete error message
    • Response body
  3. Environment Details:

    • Programming language and version
    • HTTP library and version
    • Operating system
    • Network environment (corporate, cloud, etc.)
  4. Timing Information:

    • When the issue started
    • Frequency of occurrence
    • Any recent changes

Support Channels

  • Technical Documentation: Check this wiki first
  • System Administrator: For account and permission issues
  • Development Team: For integration and technical questions
  • Help Desk: For general support requests

Self-Service Debugging

  1. Check System Status: Verify if there are known issues
  2. Review Recent Changes: Check if anything changed in your code
  3. Test with Simple Data: Use minimal test data to isolate issues
  4. Check Logs: Review application and server logs
  5. Verify Permissions: Confirm API user has necessary access

By following this troubleshooting guide, you should be able to resolve most common API submission issues quickly and efficiently.