> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cardclan.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Learn how to handle API errors gracefully and implement robust error handling in your CardClan integrations

## Overview

The CardClan Integration API uses standard HTTP status codes and provides detailed error messages to help you troubleshoot issues quickly. This guide covers common errors, their causes, and how to handle them effectively in your applications.

## HTTP Status Codes

The API uses standard HTTP status codes to indicate the success or failure of requests:

<AccordionGroup>
  <Accordion title="2xx Success Codes">
    * `200 OK` - Request successful, data returned - `201 Created` - Resource created successfully (e.g., card sent, configuration created)
  </Accordion>

  <Accordion title="4xx Client Error Codes">
    * `400 Bad Request` - Invalid request parameters or missing required fields - `401 Unauthorized` - Invalid or missing authentication credentials -
      `404 Not Found` - Requested resource doesn't exist or user doesn't have access - `409 Conflict` - Resource conflict (e.g., integration
      configuration already exists)
  </Accordion>

  <Accordion title="5xx Server Error Codes">
    * `500 Internal Server Error` - Unexpected server error - `502 Bad Gateway` - Temporary server issue - `503 Service Unavailable` - Service
      temporarily unavailable
  </Accordion>
</AccordionGroup>

## Error Response Format

All error responses follow a consistent structure:

```json theme={null}
{
  "error": "Bad Request",
  "message": "Card ID is required",
  "statusCode": 400,
  "timestamp": "2024-01-15T10:30:00.000Z"
}
```

<ResponseField name="error" type="string">
  Human-readable error type corresponding to the HTTP status
</ResponseField>

<ResponseField name="message" type="string">
  Detailed error message explaining what went wrong
</ResponseField>

<ResponseField name="statusCode" type="number">
  HTTP status code for the error
</ResponseField>

<ResponseField name="timestamp" type="string">
  ISO 8601 timestamp when the error occurred
</ResponseField>

## Common Errors and Solutions

### Authentication Errors

<AccordionGroup>
  <Accordion title="401 - Authorization header with Bearer token required">
    **Cause**: Missing `Authorization` header in your request

    **Solution**: Include the Bearer token header

    ```javascript theme={null}
    // ❌ Missing header
    fetch('/api/integration/workspaces')

    // ✅ Correct header
    fetch('/api/integration/workspaces', {
      headers: {
        'Authorization': 'Bearer your-integration-key'
      }
    })
    ```
  </Accordion>

  <Accordion title="401 - Bearer token is empty">
    **Cause**: Authorization header present but token value is empty

    **Solution**: Ensure your integration key is properly set

    ```javascript theme={null}
    // ❌ Empty token
    const token = process.env.CARDCLAN_API_KEY; // undefined

    // ✅ Check token exists
    const token = process.env.CARDCLAN_API_KEY;
    if (!token) {
      throw new Error('CARDCLAN_API_KEY environment variable not set');
    }
    ```
  </Accordion>

  <Accordion title="404 - Invalid bearer token - user not found">
    **Cause**: Integration key is invalid or has been regenerated

    **Solution**: Generate a new integration key from CardClan dashboard

    ```javascript theme={null}
    // Check if key is valid format (UUID)
    function isValidIntegrationKey(key) {
      const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
      return uuidRegex.test(key);
    }
    ```
  </Accordion>
</AccordionGroup>

### Validation Errors

<AccordionGroup>
  <Accordion title="400 - Card ID is required">
    **Cause**: Missing `card` parameter in request payload

    **Solution**: Include the card ID in your request

    ```javascript theme={null}
    // ❌ Missing card ID
    {
      "integrationId": "60f7b2b5b8f4a20015a4f5a7",
      "mergeTags": [{"name": "John", "email": "john@example.com"}]
    }

    // ✅ Include card ID
    {
      "card": "60f7b2b5b8f4a20015a4f5a5",
      "integrationId": "60f7b2b5b8f4a20015a4f5a7",
      "mergeTags": [{"name": "John", "email": "john@example.com"}]
    }
    ```
  </Accordion>

  <Accordion title="400 - Integration ID is required">
    **Cause**: Missing `integrationId` parameter

    **Solution**: Create integration configuration first, then use the returned ID

    ```javascript theme={null}
    // Create integration configuration first
    const configResponse = await fetch('/api/integration/config', {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${apiKey}` },
      body: JSON.stringify({
        userId: 'user-id',
        workspaceId: 'workspace-id',
        cardId: 'card-id'
      })
    });

    const config = await configResponse.json();
    const integrationId = config.data._id;

    // Now use integration ID in send request
    await sendCard({ integrationId, ... });
    ```
  </Accordion>

  <Accordion title="400 - mergeTags is required and must be a non-empty array">
    **Cause**: Missing or invalid `mergeTags` parameter

    **Solution**: Provide merge tags as a non-empty array

    ```javascript theme={null}
    // ❌ Missing merge tags
    {
      "card": "card-id",
      "integrationId": "integration-id"
    }

    // ❌ Empty array
    {
      "card": "card-id",
      "integrationId": "integration-id",
      "mergeTags": []
    }

    // ✅ Valid merge tags
    {
      "card": "card-id",
      "integrationId": "integration-id",
      "mergeTags": [
        {
          "name": "John Doe",
          "email": "john@example.com"
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="400 - Workspace parameter is required">
    **Cause**: Missing workspace query parameter when fetching cards

    **Solution**: Include workspace ID in the query string

    ```javascript theme={null}
    // ❌ Missing workspace parameter
    fetch('/api/integration/cards', { method: 'POST' })

    // ✅ Include workspace parameter
    fetch('/api/integration/cards?workspace=60f7b2b5b8f4a20015a4f5a4', {
      method: 'POST'
    })
    ```
  </Accordion>
</AccordionGroup>

### Resource Errors

<AccordionGroup>
  <Accordion title="404 - Card not found or you do not have access to this card">
    **Cause**: Card ID doesn't exist or user doesn't have permission to access it

    **Solution**: Verify the card exists and belongs to your workspace

    ```javascript theme={null}
    // First, get available cards for your workspace
    const cardsResponse = await fetch(`/api/integration/cards?workspace=${workspaceId}`, {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${apiKey}` }
    });

    const cards = await cardsResponse.json();
    const availableCardIds = cards[0].choices.map(card => card.id);

    if (!availableCardIds.includes(cardId)) {
      throw new Error(`Card ${cardId} not found in workspace`);
    }
    ```
  </Accordion>

  <Accordion title="409 - Integration configuration already exists">
    **Cause**: Trying to create an integration configuration for a card that already has one

    **Solution**: Get the existing configuration instead

    ```javascript theme={null}
    try {
      // Try to create new configuration
      const config = await createIntegrationConfig(cardId, workspaceId, userId);
      return config.data._id;
    } catch (error) {
      if (error.status === 409) {
        // Configuration exists, get it instead
        const existingConfig = await getIntegrationConfigByCardId(cardId);
        return existingConfig._id;
      }
      throw error;
    }
    ```
  </Accordion>

  <Accordion title="409 - Integration configuration doesn't exist">
    **Cause**: Trying to use an integration ID that doesn't exist

    **Solution**: Create the integration configuration first

    ```javascript theme={null}
    async function ensureIntegrationConfig(cardId, workspaceId, userId) {
      try {
        // Try to get existing configuration
        return await getIntegrationConfigByCardId(cardId);
      } catch (error) {
        if (error.status === 409) {
          // Doesn't exist, create it
          const config = await createIntegrationConfig(cardId, workspaceId, userId);
          return config.data;
        }
        throw error;
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

Now that you have covered the error handling:

1. [Explore examples](/examples/send-card)
2. [Explore the API reference](/api-reference/integration/overview) for detailed endpoint documentation
