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

# List DNC entries

> Retrieve a paginated list of all Do Not Contact entries for your team

## Overview

Retrieve a paginated list of all Do Not Contact (DNC) entries for your team. This endpoint returns LinkedIn URLs that have been added to your DNC list, preventing them from being contacted in any campaigns.

## Use Cases

* **Compliance Management**: Maintain a comprehensive list of contacts who have opted out
* **Data Export**: Export your DNC list for record-keeping or external systems
* **Audit Trail**: Review all blocked contacts across your organization
* **Integration**: Sync DNC data with external CRM or compliance systems
* **Monitoring**: Track the size and growth of your DNC list over time

## Key Features

* **Pagination Support**: Efficiently retrieve large DNC lists with limit and offset parameters
* **Rate Limited**: 60 requests per minute for optimal performance
* **Team Isolation**: Only see DNC entries belonging to your team
* **Sorted by Date**: Returns most recent entries first (descending order)
* **Complete Data**: Includes all entry details including creation timestamps

## Testing Example

```bash theme={null}
curl -X GET "https://api.kakiyo.com/v1/dnc?limit=50&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```javascript theme={null}
// JavaScript/Node.js
const listDNCEntries = async (limit = 50, offset = 0) => {
  const response = await fetch(`https://api.kakiyo.com/v1/dnc?limit=${limit}&offset=${offset}`, {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  });

  return await response.json();
};

// Usage example
const entries = await listDNCEntries(50, 0);
console.log('DNC Entries:', entries.data.entries);
console.log('Total:', entries.data.total);
```

```python theme={null}
# Python
import requests

def list_dnc_entries(limit=50, offset=0):
    """List all DNC entries for the team"""
    response = requests.get(
        f'https://api.kakiyo.com/v1/dnc?limit={limit}&offset={offset}',
        headers={
            'Authorization': 'Bearer YOUR_API_KEY'
        }
    )

    return response.json()

# Usage example
result = list_dnc_entries(50, 0)
print('DNC Entries:', result['data']['entries'])
print('Total:', result['data']['total'])
```

## Query Parameters

| Parameter | Type      | Required | Default | Description                              |
| --------- | --------- | -------- | ------- | ---------------------------------------- |
| `limit`   | `integer` | No       | 50      | Number of entries to return (1-1000)     |
| `offset`  | `integer` | No       | 0       | Number of entries to skip for pagination |

## Response Format

### Success Response (200 OK)

```json theme={null}
{
  "error": null,
  "data": {
    "entries": [
      {
        "$id": "dnc_12345abcde",
        "teamId": "team_67890fghij",
        "url": "https://linkedin.com/in/johnsmith",
        "$createdAt": "2025-11-18T10:30:00.000Z",
        "$updatedAt": "2025-11-18T10:30:00.000Z"
      },
      {
        "$id": "dnc_23456bcdef",
        "teamId": "team_67890fghij",
        "url": "https://linkedin.com/in/sarahjohnson",
        "$createdAt": "2025-11-17T15:20:00.000Z",
        "$updatedAt": "2025-11-17T15:20:00.000Z"
      }
    ],
    "total": 2,
    "limit": 50,
    "offset": 0
  }
}
```

### Error Responses

#### 429 Too Many Requests - Rate Limit Exceeded

```json theme={null}
{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Please try again later.",
  "resetTime": 1700308800000
}
```

#### 401 Unauthorized - Invalid API Key

```json theme={null}
{
  "error": "unauthorized",
  "message": "Invalid or missing API key"
}
```

#### 500 Internal Server Error

```json theme={null}
{
  "error": "internal_error",
  "message": "An internal error occurred"
}
```

## Pagination

This endpoint supports pagination to handle large DNC lists efficiently:

### Pagination Strategy

1. **First Page**: `GET /v1/dnc?limit=50&offset=0`
2. **Second Page**: `GET /v1/dnc?limit=50&offset=50`
3. **Third Page**: `GET /v1/dnc?limit=50&offset=100`

### Calculating Total Pages

```javascript theme={null}
const totalPages = Math.ceil(total / limit);
```

### Pagination Example

```javascript theme={null}
// Fetch all DNC entries with pagination
const fetchAllDNCEntries = async () => {
  const limit = 100;
  let offset = 0;
  let allEntries = [];
  let hasMore = true;

  while (hasMore) {
    const response = await fetch(
      `https://api.kakiyo.com/v1/dnc?limit=${limit}&offset=${offset}`,
      {
        headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
      }
    );

    const result = await response.json();
    allEntries = [...allEntries, ...result.data.entries];

    // Check if there are more entries
    hasMore = result.data.entries.length === limit;
    offset += limit;
  }

  return allEntries;
};
```

## Rate Limiting

* **Limit**: 60 requests per minute per team
* **Window**: Rolling 60-second window
* **Headers**: Rate limit information included in response headers
* **Exceeded**: Returns 429 status with `resetTime` timestamp

### Rate Limit Best Practices

1. **Implement Backoff**: Wait for `resetTime` before retrying
2. **Cache Results**: Store DNC list locally to reduce API calls
3. **Batch Operations**: Use pagination efficiently to minimize requests
4. **Monitor Usage**: Track your request count to avoid hitting limits

## Integration Examples

### Export to CSV

```javascript theme={null}
const exportDNCToCSV = async () => {
  const entries = await fetchAllDNCEntries();

  const csv = ['ID,URL,Created At'].concat(
    entries.map(entry =>
      `${entry.$id},${entry.url},${entry.$createdAt}`
    )
  ).join('\n');

  // Save to file or send to client
  return csv;
};
```

### Sync with External CRM

```javascript theme={null}
const syncDNCWithCRM = async () => {
  const limit = 100;
  let offset = 0;
  let hasMore = true;

  while (hasMore) {
    // Fetch batch from API
    const result = await listDNCEntries(limit, offset);

    // Sync with CRM
    await crmClient.updateDNCList(result.data.entries);

    // Continue pagination
    hasMore = result.data.entries.length === limit;
    offset += limit;

    // Rate limit protection
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
};
```

### Monitor DNC List Size

```javascript theme={null}
const getDNCStats = async () => {
  // Fetch first page to get total count
  const result = await listDNCEntries(1, 0);

  return {
    totalEntries: result.data.total,
    lastChecked: new Date().toISOString()
  };
};
```

## Response Data Structure

| Field          | Type      | Description                                                           |
| -------------- | --------- | --------------------------------------------------------------------- |
| `data.entries` | `array`   | Array of DNC entry objects                                            |
| `data.total`   | `integer` | **Count of entries in current response** (not total across all pages) |
| `data.limit`   | `integer` | The limit value used for this request                                 |
| `data.offset`  | `integer` | The offset value used for this request                                |

**Important Note:** The `total` field returns the number of entries in the current response (same as `entries.length`), NOT the total count of all DNC entries across all pages. To get the full count, you need to paginate through all results.

## Entry Object Structure

| Field        | Type     | Description                                    |
| ------------ | -------- | ---------------------------------------------- |
| `$id`        | `string` | Unique identifier for the DNC entry            |
| `teamId`     | `string` | Team ID that owns this entry                   |
| `url`        | `string` | Normalized LinkedIn URL                        |
| `$createdAt` | `string` | ISO 8601 timestamp when entry was created      |
| `$updatedAt` | `string` | ISO 8601 timestamp when entry was last updated |

## Best Practices

1. **Use Pagination**: Don't fetch all entries at once; use limit/offset for large lists
2. **Cache Locally**: Store DNC list locally and refresh periodically
3. **Rate Limit Awareness**: Implement exponential backoff for 429 responses
4. **Error Handling**: Always check for `error` field in response
5. **Audit Trail**: Maintain local logs of DNC list state for compliance
6. **Regular Sync**: Sync DNC list with external systems periodically
7. **Monitor Growth**: Track DNC list size over time for compliance reporting

## Performance Considerations

* **Database Indexed**: Queries are optimized with composite index on `teamId`
* **Response Time**: Typically \< 200ms for lists under 1000 entries
* **Sorted Results**: Entries returned in descending order by creation date
* **Team Isolation**: Permissions enforced at database level for security

## Common Use Cases

### Daily Export for Compliance

```javascript theme={null}
const dailyDNCExport = async () => {
  const entries = await fetchAllDNCEntries();

  // Create compliance report
  const report = {
    date: new Date().toISOString(),
    totalEntries: entries.length,
    entries: entries.map(e => ({
      url: e.url,
      addedAt: e.$createdAt
    }))
  };

  // Save to compliance system
  await complianceSystem.saveReport(report);
};

// Run daily
setInterval(dailyDNCExport, 24 * 60 * 60 * 1000);
```

### Real-time Dashboard

```javascript theme={null}
const dncDashboard = async () => {
  const result = await listDNCEntries(10, 0);

  return {
    recentlyAdded: result.data.entries.slice(0, 5),
    total: result.data.total,
    todayAdded: result.data.entries.filter(e =>
      new Date(e.$createdAt).toDateString() === new Date().toDateString()
    ).length
  };
};
```

## Next Steps

After listing DNC entries:

1. **Check Specific URLs**: Use [Check DNC](/api-reference/dnc/check) endpoint
2. **Add New Entries**: Use [Add Single](/api-reference/dnc/add-single) or [Bulk Add](/api-reference/dnc/add-batch) endpoints
3. **Remove Entries**: Use [Delete DNC](/api-reference/dnc/delete) endpoint
4. **Export Data**: Integrate with external systems using the list data

## Related Endpoints

* [Check DNC](/api-reference/dnc/check) - Check if a URL is on the DNC list
* [Add Single Entry](/api-reference/dnc/add-single) - Add a single URL to DNC list
* [Bulk Add Entries](/api-reference/dnc/add-batch) - Add multiple URLs to DNC list
* [Delete Entry](/api-reference/dnc/delete) - Remove a URL from DNC list


## OpenAPI

````yaml GET /dnc
openapi: 3.1.0
info:
  title: Kakiyo API
  description: API for automating LinkedIn outreach campaigns with AI-powered conversations
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.kakiyo.com/v1
security:
  - bearerAuth: []
paths:
  /dnc:
    get:
      summary: List DNC entries
      description: Retrieve a paginated list of all Do Not Contact entries for your team
      operationId: listDNC
      parameters:
        - name: limit
          in: query
          description: Number of entries to return (1-1000)
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 1000
        - name: offset
          in: query
          description: Number of entries to skip for pagination
          schema:
            type: integer
            minimum: 0
            default: 0
      responses:
        '200':
          description: List of DNC entries
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: 'null'
                  data:
                    type: object
                    properties:
                      entries:
                        type: array
                        items:
                          $ref: '#/components/schemas/DNCEntry'
                      total:
                        type: integer
                        description: >-
                          Count of entries in current response (not total across
                          all pages)
                        example: 2
                      limit:
                        type: integer
                        example: 50
                      offset:
                        type: integer
                        example: 0
        '401':
          description: Authentication failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RateLimitError'
components:
  schemas:
    DNCEntry:
      type: object
      properties:
        $id:
          type: string
          description: Unique identifier for the DNC entry
          example: dnc_12345abcde
        teamId:
          type: string
          description: Team ID that owns this entry
          example: team_67890fghij
        url:
          type: string
          description: Normalized LinkedIn profile URL
          example: https://linkedin.com/in/johnsmith
        $createdAt:
          type: string
          format: date-time
          description: Timestamp when entry was created
          example: '2025-11-18T10:30:00.000Z'
        $updatedAt:
          type: string
          format: date-time
          description: Timestamp when entry was last updated
          example: '2025-11-18T10:30:00.000Z'
    Error:
      type: object
      properties:
        error:
          type: string
          example: validation_error
        message:
          type: string
          example: The request parameters failed validation
        details:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
                example: name
              message:
                type: string
                example: The name field is required
    RateLimitError:
      type: object
      properties:
        error:
          type: string
          example: rate_limit_exceeded
        message:
          type: string
          example: Too many requests. Please try again later.
        resetTime:
          type: integer
          format: int64
          description: Unix timestamp (in milliseconds) when the rate limit resets
          example: 1700308800000
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````