API Error Reference

This guide documents all error codes, response formats, and troubleshooting steps for the TeamDay API.


Error Response Format

All API errors follow a consistent JSON structure:

{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Detailed error description"
}

Fields:

  • error (boolean) - Always true for error responses
  • statusCode (number) - HTTP status code
  • statusMessage (string) - Human-readable status
  • message (string) - Detailed error explanation

HTTP Status Codes

2xx Success

These are not errors, but successful responses:

200 OK

Meaning: Request succeeded

Used by:

  • GET requests (list, get details)
  • PATCH requests (update)
  • DELETE requests (soft delete)
  • POST requests (cancel execution)

Example:

{
  "id": "agent_abc123",
  "name": "Research Assistant",
  "...": "..."
}

201 Created

Meaning: Resource successfully created

Used by:

  • POST requests (create agent, task)

Example:

{
  "id": "agent_abc123",
  "name": "Research Assistant",
  "createdAt": "2025-12-09T10:00:00Z",
  "...": "..."
}

4xx Client Errors

These errors indicate problems with the request.

400 Bad Request

Meaning: Invalid request parameters or missing required fields

Common causes:

  • Missing required fields
  • Invalid field values
  • Malformed JSON
  • Invalid query parameters

Examples:

Missing required field:

{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Missing required field: name"
}

Invalid visibility value:

{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Invalid visibility value. Must be: private, organization, or public"
}

Invalid status:

{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Invalid status. Must be: pending, in_progress, completed, cancelled"
}

Malformed JSON:

{
  "error": true,
  "statusCode": 400,
  "statusMessage": "Bad Request",
  "message": "Invalid JSON in request body"
}

How to fix:

  1. Check request body matches API documentation
  2. Validate all required fields are present
  3. Verify field values are valid (enums, types)
  4. Test JSON syntax with a validator

401 Unauthorized

Meaning: Authentication failed or missing

Common causes:

  • Missing Authorization header
  • Invalid token
  • Expired token
  • Token format incorrect

Examples:

Missing header:

{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Authorization header required"
}

Invalid token:

{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Invalid or expired token"
}

Expired token:

{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Token expired"
}

Wrong format:

{
  "error": true,
  "statusCode": 401,
  "statusMessage": "Unauthorized",
  "message": "Token must start with 'td_'"
}

How to fix:

  1. Check Authorization header is present
  2. Verify header format: Authorization: Bearer td_xxxxx...
  3. Confirm token not expired in Settings → API Access
  4. Generate new token if needed
  5. Check token copied correctly (no extra spaces)

403 Forbidden

Meaning: Authenticated but not authorized for this action

Common causes:

  • User lacks required permissions
  • Organization access revoked
  • Resource belongs to different organization

Example:

{
  "error": true,
  "statusCode": 403,
  "statusMessage": "Forbidden",
  "message": "You don't have permission to access this resource"
}

How to fix:

  1. Verify user has correct role/permissions
  2. Check user still belongs to organization
  3. Confirm resource belongs to your organization
  4. Contact organization admin for permission changes

404 Not Found

Meaning: Resource doesn't exist

Common causes:

  • Invalid resource ID
  • Resource was deleted
  • Resource belongs to different organization
  • Typo in endpoint URL

Examples:

Agent not found:

{
  "error": true,
  "statusCode": 404,
  "statusMessage": "Not Found",
  "message": "Agent not found"
}

Execution not found:

{
  "error": true,
  "statusCode": 404,
  "statusMessage": "Not Found",
  "message": "Execution not found"
}

Task not found:

{
  "error": true,
  "statusCode": 404,
  "statusMessage": "Not Found",
  "message": "Task not found"
}

How to fix:

  1. Verify resource ID is correct
  2. Check resource wasn't deleted
  3. Confirm resource belongs to your organization
  4. List resources to find correct ID
  5. Check for typos in URL

429 Too Many Requests

Meaning: Rate limit exceeded

Status: Not currently enforced, but may be in future

Example:

{
  "error": true,
  "statusCode": 429,
  "statusMessage": "Too Many Requests",
  "message": "Rate limit exceeded. Retry after 60 seconds."
}

How to fix:

  1. Implement exponential backoff
  2. Reduce request frequency
  3. Cache responses when possible
  4. Contact support for higher limits

5xx Server Errors

These errors indicate problems on the server side.

500 Internal Server Error

Meaning: Unexpected server error

Common causes:

  • Database connectivity issues
  • Service dependency failure
  • Unhandled exception
  • Configuration error

Example:

{
  "error": true,
  "statusCode": 500,
  "statusMessage": "Internal Server Error",
  "message": "An unexpected error occurred"
}

Known issues:

Agent execution broken:

{
  "error": true,
  "statusCode": 500,
  "statusMessage": "Internal Server Error",
  "message": "Chat execution failed"
}

Cause: Internal /api/claude-code/chat endpoint issue

Workaround: Use web interface for agent execution

How to fix:

  1. Retry request (may be transient)
  2. Check API status page
  3. Wait a few minutes and retry
  4. Contact support if persistent
  5. Check for known issues in documentation

503 Service Unavailable

Meaning: Service temporarily unavailable

Common causes:

  • Scheduled maintenance
  • System overload
  • Dependency service down

Example:

{
  "error": true,
  "statusCode": 503,
  "statusMessage": "Service Unavailable",
  "message": "Service temporarily unavailable. Please retry."
}

How to fix:

  1. Wait and retry with exponential backoff
  2. Check status page for maintenance windows
  3. Contact support if prolonged outage

Error Handling Best Practices

1. Always Check Status Codes

const response = await fetch('https://cc.teamday.ai/api/v1/agents', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
})

if (!response.ok) {
  const error = await response.json()
  console.error(`API Error ${error.statusCode}: ${error.message}`)
  // Handle error appropriately
}

const data = await response.json()

2. Handle Specific Error Cases

async function handleApiError(response) {
  const error = await response.json()

  switch (error.statusCode) {
    case 400:
      // Validation error - fix request
      console.error('Invalid request:', error.message)
      break

    case 401:
      // Auth error - refresh token or re-authenticate
      console.error('Authentication failed:', error.message)
      await refreshToken()
      break

    case 404:
      // Not found - resource doesn't exist
      console.error('Resource not found:', error.message)
      break

    case 500:
      // Server error - retry with backoff
      console.error('Server error:', error.message)
      await retryWithBackoff()
      break

    default:
      console.error('Unexpected error:', error)
  }
}

3. Implement Retry Logic

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, options)

      if (response.ok) {
        return await response.json()
      }

      const error = await response.json()

      // Don't retry client errors (4xx)
      if (error.statusCode >= 400 && error.statusCode < 500) {
        throw new Error(error.message)
      }

      // Retry server errors (5xx) with exponential backoff
      if (i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000 // 1s, 2s, 4s
        console.log(`Retrying in ${delay}ms...`)
        await new Promise(resolve => setTimeout(resolve, delay))
        continue
      }

      throw new Error(error.message)

    } catch (err) {
      if (i === maxRetries - 1) throw err
    }
  }
}

4. Log Errors Appropriately

async function makeApiRequest(endpoint, options) {
  try {
    const response = await fetch(endpoint, options)

    if (!response.ok) {
      const error = await response.json()

      // Log error details (but not sensitive data)
      console.error('API Error:', {
        endpoint,
        statusCode: error.statusCode,
        message: error.message,
        timestamp: new Date().toISOString()
        // Don't log: tokens, passwords, PII
      })

      throw error
    }

    return await response.json()

  } catch (err) {
    // Log exception
    console.error('Request failed:', {
      endpoint,
      error: err.message,
      timestamp: new Date().toISOString()
    })

    throw err
  }
}

5. Provide User-Friendly Messages

function getUserFriendlyError(apiError) {
  const messages = {
    400: 'Invalid request. Please check your input.',
    401: 'Authentication failed. Please log in again.',
    403: 'You don\'t have permission to perform this action.',
    404: 'The requested resource was not found.',
    429: 'Too many requests. Please try again later.',
    500: 'Server error. Please try again.',
    503: 'Service temporarily unavailable. Please try again soon.'
  }

  return messages[apiError.statusCode] || 'An unexpected error occurred.'
}

// Usage
try {
  const data = await createAgent(agentData)
} catch (err) {
  const userMessage = getUserFriendlyError(err)
  showErrorToUser(userMessage)
}

Common Error Scenarios

Scenario 1: Token Expired

Error:

{
  "statusCode": 401,
  "message": "Token expired"
}

Solution:

async function ensureValidToken() {
  try {
    // Test token
    const response = await fetch('https://cc.teamday.ai/api/v1/agents', {
      headers: { 'Authorization': `Bearer ${token}` }
    })

    if (response.status === 401) {
      console.log('Token expired, generating new one...')
      // Redirect to dashboard to generate new token
      window.location.href = 'https://cc.teamday.ai/settings/api'
    }

  } catch (err) {
    console.error('Token validation failed:', err)
  }
}

Scenario 2: Missing Required Field

Error:

{
  "statusCode": 400,
  "message": "Missing required field: name"
}

Solution:

async function createAgent(agentData) {
  // Validate required fields before API call
  const required = ['name', 'systemPrompt']

  for (const field of required) {
    if (!agentData[field]) {
      throw new Error(`Missing required field: ${field}`)
    }
  }

  // Make API call
  const response = await fetch('https://cc.teamday.ai/api/v1/agents', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(agentData)
  })

  if (!response.ok) {
    const error = await response.json()
    throw error
  }

  return await response.json()
}

Scenario 3: Agent Not Found

Error:

{
  "statusCode": 404,
  "message": "Agent not found"
}

Solution:

async function getAgentSafely(agentId) {
  try {
    const response = await fetch(
      `https://cc.teamday.ai/api/v1/agents/${agentId}`,
      {
        headers: { 'Authorization': `Bearer ${token}` }
      }
    )

    if (response.status === 404) {
      console.log(`Agent ${agentId} not found. Might be deleted.`)
      return null
    }

    if (!response.ok) {
      throw await response.json()
    }

    return await response.json()

  } catch (err) {
    console.error('Failed to fetch agent:', err)
    return null
  }
}

Scenario 4: Server Error (500)

Error:

{
  "statusCode": 500,
  "message": "Internal server error"
}

Solution:

async function createAgentWithRetry(agentData) {
  const maxRetries = 3

  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch('https://cc.teamday.ai/api/v1/agents', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(agentData)
      })

      if (response.ok) {
        return await response.json()
      }

      const error = await response.json()

      // Only retry server errors
      if (error.statusCode >= 500 && i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000
        console.log(`Server error. Retrying in ${delay}ms...`)
        await new Promise(resolve => setTimeout(resolve, delay))
        continue
      }

      throw error

    } catch (err) {
      if (i === maxRetries - 1) {
        console.error('All retries failed:', err)
        throw err
      }
    }
  }
}

Debugging Tips

1. Check Request Headers

# Use curl -v for verbose output
curl -v https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN"

# Check headers being sent

2. Validate JSON

# Use jq to validate JSON
echo '{
  "name": "Test Agent",
  "systemPrompt": "You are helpful"
}' | jq .

# Should output formatted JSON if valid

3. Test Authentication

# Quick auth test
curl https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN"

# Should return 200 with agent list (or empty array)

4. Inspect Response Headers

# Check response headers
curl -I https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer $TEAMDAY_TOKEN"

# Look for:
# - HTTP status code
# - Content-Type
# - Error details

5. Use API Testing Tools

Recommended tools:

  • Postman - Full-featured API testing
  • Insomnia - Lightweight alternative
  • curl - Command-line testing
  • HTTPie - User-friendly curl alternative

Postman example:

POST https://cc.teamday.ai/api/v1/agents
Headers:
  Authorization: Bearer td_xxxxx...
  Content-Type: application/json
Body:
  {
    "name": "Test Agent",
    "systemPrompt": "You are helpful"
  }

Error Reference Table

Quick reference for all API errors:

CodeMessageCauseSolution
400Missing required fieldRequired field omittedAdd missing field
400Invalid JSONMalformed JSON bodyValidate JSON syntax
400Invalid visibilityWrong enum valueUse: private, organization, public
400Invalid statusWrong enum valueUse: pending, in_progress, completed, cancelled
400Invalid priorityWrong enum valueUse: low, medium, high, urgent
400Cannot cancelAlready completedOnly cancel pending/running executions
401Authorization header requiredMissing headerAdd Authorization header
401Invalid or expired tokenBad tokenGenerate new token
401Token expiredToken past expirationGenerate new token
403No permissionInsufficient permissionsCheck user role
404Agent not foundInvalid agent IDVerify agent exists
404Execution not foundInvalid execution IDVerify execution exists
404Task not foundInvalid task IDVerify task exists
429Rate limit exceededToo many requestsImplement backoff
500Internal server errorServer issueRetry with backoff
500Chat execution failedKnown issueUse web interface
503Service unavailableMaintenance/overloadWait and retry

Getting Help

Check Documentation

  1. API Overview - General API information
  2. Authentication - Token setup
  3. Agents API - Agent endpoints
  4. Executions API - Execution endpoints
  5. Tasks API - Task endpoints

Contact Support

Email: [email protected]

Include in support request:

  • Error message (full JSON)
  • Request details (endpoint, method, headers - WITHOUT token)
  • Steps to reproduce
  • Expected vs. actual behavior

Example support request:

Subject: 500 Error Creating Agent

I'm getting a 500 error when creating an agent via the API.

Error:
{
  "statusCode": 500,
  "message": "Internal server error"
}

Request:
POST /api/v1/agents
Headers: Authorization: Bearer td_*****, Content-Type: application/json
Body: {"name": "Test", "systemPrompt": "You are helpful"}

Expected: 201 Created with agent object
Actual: 500 Internal Server Error

I've tried retrying 3 times with same result.

Community Resources

Discord: Join community

GitHub Issues: Report bugs

Status Page: Check for known issues and maintenance


Last Updated: December 9, 2025