Error Response Format

All Mark2Notion API errors follow a consistent format to help you handle them programmatically.

Response Types

Success Response

{
  "status": "success",
  "data": {
    // Response data
  }
}

Validation Errors (400)

Used when request parameters are invalid or missing.
{
  "status": "fail",
  "data": {
    "field_name": "Error description for this field",
    "another_field": "Another validation error"
  }
}

Authentication Errors (401, 403)

{
  "status": "error",
  "message": "Authentication error description"
}

Rate Limit Errors (429)

{
  "status": "error",
  "message": "Usage quota exceeded for current billing period",
  "data": {
    "current_usage": 1000,
    "quota": 1000,
    "plan": "free",
    "requests_remaining": 0
  }
}

Server Errors (500)

{
  "status": "error",
  "message": "Internal server error description"
}

Common Error Scenarios

Authentication Issues

Usage Limits

Content Validation

Error Handling Best Practices

1. Check Response Status

Always check the HTTP status code and response status field:
const response = await fetch('/api/convert', {
  // ... request options
});

if (!response.ok) {
  const error = await response.json();
  
  switch (response.status) {
    case 400:
      // Handle validation errors
      console.log('Validation errors:', error.data);
      break;
    case 401:
    case 403:
      // Handle authentication errors
      console.log('Auth error:', error.message);
      break;
    case 429:
      // Handle rate limiting
      console.log('Rate limited:', error.data);
      break;
    default:
      console.log('Unexpected error:', error.message);
  }
  return;
}

const data = await response.json();
// Handle success

2. Implement Retry Logic

For rate limiting and transient errors:
async function callAPIWithRetry(apiCall, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await apiCall();
      
      if (response.status === 429) {
        // Rate limited - wait and retry
        const waitTime = Math.pow(2, attempt) * 1000; // Exponential backoff
        await new Promise(resolve => setTimeout(resolve, waitTime));
        continue;
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
  }
}

3. Monitor Usage

Track your API usage to avoid hitting limits:
function logUsageInfo(response) {
  const usage = {
    current: response.headers.get('X-Usage-Current'),
    quota: response.headers.get('X-Usage-Quota'),
    remaining: response.headers.get('X-Usage-Remaining'),
    plan: response.headers.get('X-Usage-Plan')
  };
  
  console.log('API Usage:', usage);
  
  // Warn when approaching limit
  if (usage.remaining < usage.quota * 0.1) {
    console.warn('Approaching usage limit!');
  }
}

4. Graceful Degradation

Handle errors gracefully in your application:
async function convertMarkdown(markdown) {
  try {
    const response = await callAPI('/api/convert', { markdown });
    return response.data.blocks;
  } catch (error) {
    // Log error for debugging
    console.error('Markdown conversion failed:', error);
    
    // Return fallback or throw user-friendly error
    throw new Error('Unable to convert markdown at this time. Please try again later.');
  }
}

Getting Help

If you encounter errors not covered here:
When reporting issues, include the full error response and the request that caused it (without sensitive data like API keys).