Skip to content

Errors

In this guide, we'll talk about what happens when something goes wrong while you work with the API. Let's look at status codes and error types you might encounter.

You can tell if your request was successful by checking the status code in the API response. If unsuccessful, use the error type and message to debug before contacting support.


Status codes

Here are the different categories of status codes returned by the Schedule Intelligence APIs:

  • 200 - OK: Request successful. Response body contains the requested data.

  • 400 - Bad Request: Invalid request format or parameters. Check the error message for details.

  • 401 - Unauthorized: Missing or invalid API key. Check your x-api-key header.

  • 422 - Unprocessable Entity: Request validation failed. Check your request schema against the API spec.

  • 429 - Too Many Requests: Rate limit exceeded. Check Retry-After header and wait before retrying.

  • 500 - Internal Server Error: Server error. Retry with exponential backoff. Contact support if persists.


Common error types

Validation errors

Validation errors occur when your request doesn't match the expected schema:

{
  "detail": [
    {
      "loc": ["body", "tasks", 0, "duration"],
      "msg": "ensure this value is greater than 0",
      "type": "value_error.number.not_gt"
    }
  ]
}

Common causes:

  • Missing required fields
  • Invalid data types
  • Values outside allowed ranges
  • Invalid dependency references

Schedule validation errors

Schedule-specific validation errors:

{
  "detail": {
    "errors": [
      {
        "task_id": "T5",
        "error": "Circular dependency detected: T1 -> T2 -> T5 -> T1"
      }
    ],
    "is_valid": false
  }
}

Common causes:

  • Circular dependencies
  • Missing task references
  • Negative durations
  • Invalid relationship types (must be FS, SS, FF, SF)

Rate limit errors

When you exceed your tier's rate limit:

{
  "detail": "Rate limit exceeded: 100 requests per 60 seconds. Retry after 45 seconds.",
  "retry_after": 45
}

Response headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1738195200
Retry-After: 45

How to handle:

  1. Check Retry-After header
  2. Wait the specified time before retrying
  3. Implement exponential backoff
  4. Consider upgrading your tier

Task limit errors

When your schedule exceeds your tier's task limit:

{
  "detail": "Task count 3000 exceeds tier limit of 2000. Upgrade for a higher task limit, or use async processing on Starter+."
}

Solutions:

  • Upgrade for a higher per-request task limit
  • Use async processing endpoints on Starter+
  • Split large schedules into smaller chunks

Async job errors

When checking async job status:

{
  "job_id": "job_abc123",
  "status": "failed",
  "error": {
    "type": "processing_error",
    "message": "Critical path calculation failed: memory limit exceeded",
    "timestamp": "2026-01-29T12:05:00Z"
  }
}

Common causes:

  • Schedule too complex (>100,000 tasks)
  • Memory exhaustion
  • Processing timeout
  • Invalid schedule structure

Error handling best practices

Retry with exponential backoff

import time
from requests.exceptions import RequestException

def make_request_with_retry(url, data, max_retries=5):
    for attempt in range(max_retries):
        try:
            response = requests.post(url, json=data)
            
            if response.status_code == 429:
                # Rate limited - respect Retry-After
                retry_after = int(response.headers.get('Retry-After', 60))
                time.sleep(retry_after)
                continue
            
            if response.status_code >= 500:
                # Server error - exponential backoff
                time.sleep(2 ** attempt)
                continue
            
            response.raise_for_status()
            return response.json()
            
        except RequestException as e:
            if attempt == max_retries - 1:
                raise
            time.sleep(2 ** attempt)
    
    raise Exception("Max retries exceeded")

Validate before sending

Validate request payloads locally before calling the API (schema fields, non-negative durations, known task IDs in predecessors). Prefer catching 400 validation errors from the API and fixing the payload rather than retrying invalid bodies.

Log errors with context

import structlog

logger = structlog.get_logger()

try:
    response = client.get_schedule_health(request)
except Exception as e:
    logger.error(
        "schedule_health_failed",
        error=str(e),
        task_count=len(request.tasks),
        request_id=request_id
    )
    raise

Getting help

If you encounter persistent errors:

  1. Check this guide for common error patterns
  2. Review API documentation at /docs/api-reference
  3. Try the playground at /playground to test requests
  4. Check status page for known issues
  5. Contact support with request ID and full error response

Always include the X-Request-ID header value when contacting support. This helps us quickly locate your request in our logs.

Next steps

Was this page helpful?

Your feedback helps us improve docs, reference pages, and Playground flows.

Topic: Error Codes · Page: /docs/errors

TermsPrivacyContact

Schedule analysis guidance. Not legal advice. You remain responsible for contract and agency compliance.