Skip to main content
GET
/
dnc
List DNC entries
curl --request GET \
  --url https://api.kakiyo.com/v1/dnc \
  --header 'Authorization: Bearer <token>'
{
  "error": "<unknown>",
  "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"
      }
    ],
    "total": 2,
    "limit": 50,
    "offset": 0
  }
}

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

curl -X GET "https://api.kakiyo.com/v1/dnc?limit=50&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
// 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
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

ParameterTypeRequiredDefaultDescription
limitintegerNo50Number of entries to return (1-1000)
offsetintegerNo0Number of entries to skip for pagination

Response Format

Success Response (200 OK)

{
  "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

{
  "error": "rate_limit_exceeded",
  "message": "Too many requests. Please try again later.",
  "resetTime": 1700308800000
}

401 Unauthorized - Invalid API Key

{
  "error": "unauthorized",
  "message": "Invalid or missing API key"
}

500 Internal Server Error

{
  "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

const totalPages = Math.ceil(total / limit);

Pagination Example

// 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

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

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

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

FieldTypeDescription
data.entriesarrayArray of DNC entry objects
data.totalintegerCount of entries in current response (not total across all pages)
data.limitintegerThe limit value used for this request
data.offsetintegerThe 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

FieldTypeDescription
$idstringUnique identifier for the DNC entry
teamIdstringTeam ID that owns this entry
urlstringNormalized LinkedIn URL
$createdAtstringISO 8601 timestamp when entry was created
$updatedAtstringISO 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

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

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 endpoint
  2. Add New Entries: Use Add Single or Bulk Add endpoints
  3. Remove Entries: Use Delete DNC endpoint
  4. Export Data: Integrate with external systems using the list data

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Query Parameters

limit
integer
default:50

Number of entries to return (1-1000)

Required range: 1 <= x <= 1000
offset
integer
default:0

Number of entries to skip for pagination

Required range: x >= 0

Response

List of DNC entries

error
null
data
object