Error Handling

Understanding and handling API errors in your SuperSend integration.


SuperSend uses conventional HTTP response codes and returns detailed error information to help you handle issues gracefully.

ℹ️

V2 Standardized Errors

V2 API provides standardized error responses with machine-readable codes, while V1 has varied response formats.


HTTP Status Codes

CodeMeaningV1V2

200Success - Request completed successfully✅✅
201Created - New resource was created✅✅
400Bad Request - Invalid parameters✅✅
401Unauthorized - Invalid or missing API key✅✅
403Forbidden - Valid key but insufficient permissions✅✅
404Not Found - Resource doesn't exist✅✅
409Conflict - Resource state conflict✅✅
422Unprocessable Entity - Validation error✅❌
429Too Many Requests - Rate limit exceeded✅✅
500Internal Server Error - Server-side issue✅✅
503Service Unavailable - Temporary outage✅✅

Note: V2 uses 400 for all validation errors. V1 may use 422 in some endpoints.


V2 Error Response Format

All V2 errors follow this structure:

json
{
"error": {
"type": "invalid_request_error",
"code": "missing_required_parameter",
"message": "TeamId is required",
"param": "TeamId",
"doc_url": "https://docs.supersend.io/docs/error-handling#missing_required_parameter"
},
"request_id": "req_a1b2c3d4e5f6789012345678"
}

FieldTypeDescription

typestringError category
codestringMachine-readable error code
messagestringHuman-readable description
paramstringParameter that caused error (optional)
doc_urlstringDocumentation link (optional)
request_idstringUnique request identifier


V1 Error Response Format

V1 responses vary but typically follow:

json
{
"success": false,
"error": "CampaignId is required"
}

Or in some endpoints:

json
{
"error": "Not found"
}


Error Types (V2)

TypeHTTP StatusDescription

invalid_request_error400Invalid parameters or malformed request
authentication_error401Invalid or missing API key
authorization_error403Valid key but insufficient permissions
not_found_error404Resource doesn't exist
conflict_error409Resource state conflict
rate_limit_error429Too many requests
api_error500Internal server error


Common Error Codes

Authentication Errors

invalid_api_key or missing_api_key


Your API key is missing or invalid.

json
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key provided"
}
}

Fix: Include a valid Authorization: Bearer YOUR_API_KEY header.

team_access_denied


You don't have access to the requested team.

json
{
"error": {
"type": "authorization_error",
"code": "team_access_denied",
"message": "You do not have access to this team"
}
}

Fix: Verify you're accessing a team your API key has access to.


Validation Errors

missing_required_parameter


A required parameter was not provided.

json
{
"error": {
"type": "invalid_request_error",
"code": "missing_required_parameter",
"message": "TeamId is required",
"param": "TeamId"
}
}

Fix: Include the missing parameter in your request.

validation_error


Request data failed validation.

json
{
"error": {
"type": "invalid_request_error",
"code": "validation_error",
"message": "email must be a valid email address",
"param": "email"
}
}

Fix: Ensure the parameter matches the expected format.

invalid_parameter_type


Parameter has wrong data type.

json
{
"error": {
"type": "invalid_request_error",
"code": "invalid_parameter_type",
"message": "limit must be a number",
"param": "limit"
}
}


Resource Errors

resource_not_found


The requested resource doesn't exist.

json
{
"error": {
"type": "not_found_error",
"code": "resource_not_found",
"message": "Resource not found"
}
}

Fix: Verify the resource ID is correct.

campaign_not_found


Campaign doesn't exist or you don't have access.

json
{
"error": {
"type": "not_found_error",
"code": "campaign_not_found",
"message": "Campaign not found"
}
}

contact_not_found


Contact doesn't exist.

json
{
"error": {
"type": "not_found_error",
"code": "contact_not_found",
"message": "Contact not found"
}
}


Business Logic Errors

insufficient_permissions


A usage limit has been exceeded or you don't have permission for this action.

json
{
"error": {
"type": "authorization_error",
"code": "insufficient_permissions",
"message": "Contact limit reached"
}
}

Fix: Upgrade your plan or reduce usage to stay within limits.

duplicate_resource


Resource already exists.

json
{
"error": {
"type": "conflict_error",
"code": "duplicate_resource",
"message": "Contact with this email already exists in this campaign"
}
}


Handling Errors

JavaScript/Node.js

javascript
async function makeApiRequest(url, options) {
try {
const response = await fetch(url, {
...options,
headers: {
'Authorization': Bearer ${process.env.SUPERSEND_API_KEY},
'Content-Type': 'application/json',
...options.headers
}
});

const data = await response.json();

if (!response.ok) {
// V2 error format
const error = data.error || {};
console.error(API Error [${error.code}]: ${error.message});
console.error(Request ID: ${data.request_id});

switch (error.type) {
case 'authentication_error':
throw new Error('Check your API key');
case 'not_found_error':
throw new Error('Resource not found');
case 'invalid_request_error':
throw new Error(Validation error: ${error.param});
default:
throw new Error(error.message || 'Unknown error');
}
}

return data;
} catch (err) {
console.error('Request failed:', err.message);
throw err;
}
}

Python

python
import requests

def make_api_request(url, method='GET', kwargs):
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json',
kwargs.get('headers', {})
}

response = requests.request(method, url, headers=headers, kwargs)
data = response.json()

if not response.ok:
error = data.get('error', {})
print(fclass="text-green-700 dark:text-green-400">"API Error [{error.get('code')}]: {error.get('message')}")
print(fclass="text-green-700 dark:text-green-400">"Request ID: {data.get('request_id')}")

if error.get('type') == 'authentication_error':
raise Exception('Check your API key')
elif error.get('type') == 'not_found_error':
raise Exception('Resource not found')
else:
raise Exception(error.get('message', 'Unknown error'))

return data


Request ID for Debugging

Every response includes a unique request_id:

  • In response body: "request_id": "req_a1b2c3d4e5f6789012345678"

  • In response header: X-Request-Id: req_a1b2c3d4e5f6789012345678
  • When contacting support, always include the request ID for faster debugging.


    Best Practices

    1. Check Error Types Programmatically

    javascript
    if (error.type === 'authentication_error') {
    // Refresh token or re-authenticate
    } else if (error.type === 'not_found_error') {
    // Resource doesn't exist
    } else if (error.type === 'invalid_request_error') {
    // Fix request parameters
    }

    2. Log Request IDs

    Always log request IDs for troubleshooting:

    javascript
    console.log(Request ${data.request_id}: ${response.status});

    3. Handle Retries for Server Errors

    Retry 5xx errors with exponential backoff:

    javascript
    async function retryRequest(fn, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
    try {
    return await fn();
    } catch (err) {
    if (err.status >= 500 && i < maxRetries - 1) {
    await sleep(Math.pow(2, i) * 1000);
    continue;
    }
    throw err;
    }
    }
    }

    4. Don't Retry Client Errors

    4xx errors indicate problems with your request. Fix the issue rather than retrying.