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

# List / Check Do-Not-Contact

> List your workspace's Do-Not-Contact entries, poll for new opt-outs with since=, or check one phone number or email. REST endpoint in the Tuco AI iMessage API — bearer-token auth.

<Note>
  Use this to stop contacts on your other channels (WhatsApp, email, dialer) when they opt out on iMessage. Poll with `since=`, or subscribe to the [`dnc.added` webhook](/api-reference/message-webhooks#dnc-added) to hear about each opt-out as it happens.
</Note>

## Authentication

```bash theme={null}
Authorization: Bearer tuco_xxxxxxxxxxxxx
```

Rate limit: 120 requests per minute per workspace (`429` with `Retry-After`).

Without `since`, entries are returned newest first.

***

## Examples

<CodeGroup>
  ```bash Poll for new opt-outs theme={null}
  curl "https://app.tuco.ai/api/dnc?since=2026-10-19T11:32:45Z&limit=200" \
    -H "Authorization: Bearer tuco_xxxxxxxxxxxxx"
  ```

  ```bash Check one number theme={null}
  curl "https://app.tuco.ai/api/dnc?phone=%2B15550100777" \
    -H "Authorization: Bearer tuco_xxxxxxxxxxxxx"
  ```

  ```bash List all (paged) theme={null}
  curl "https://app.tuco.ai/api/dnc?page=1&limit=200" \
    -H "Authorization: Bearer tuco_xxxxxxxxxxxxx"
  ```
</CodeGroup>

### Polling loop

1. Store the `addedAt` of the last entry you processed (start with any past date).
2. Call `GET /api/dnc?since=<that addedAt>&limit=200`.
3. Skip ids you have already processed; process the rest.
4. If `hasMore` is `true`, read `page=2`, `page=3`, … with the same `since`.
5. Save the last entry's `addedAt` and repeat (every few minutes is plenty).

***

## Success response (200)

```json Check one number theme={null}
{
  "entries": [
    {
      "id": "6ad5ffeb89a6125f30a7dd2c",
      "phone": "+15550100777",
      "email": null,
      "reason": "opt-out",
      "addedBy": "system",
      "addedAt": "2026-10-19T11:32:59.433Z",
      "source": "keyword-STOP"
    }
  ],
  "total": 1,
  "page": 1,
  "limit": 50,
  "totalPages": 1,
  "hasMore": false,
  "listed": true
}
```

## Errors

| Status | When |
| - | - |
| `400` | `since` is not a valid date |
| `401` | Missing or invalid API key |
| `429` | Rate limit exceeded |


## OpenAPI

````yaml GET /api/dnc
openapi: 3.1.0
info:
  title: Tuco AI API
  description: >-
    Send iMessages, SMS, and email at scale. Create leads, get lines, check
    replies. All endpoints support Bearer API key (`Authorization: Bearer
    tuco_...`).
  version: 1.0.0
  contact:
    email: support@tuco.ai
    url: https://app.tuco.ai
servers:
  - url: https://app.tuco.ai
    description: Production
security:
  - bearerAuth: []
paths:
  /api/dnc:
    get:
      summary: List / check Do-Not-Contact
      description: >-
        List Do-Not-Contact entries, poll for new opt-outs with `since`, or
        check one contact with `phone` / `email` (adds `listed`). Without
        `since`, newest first; with `since`, oldest first.
      operationId: listDnc
      parameters:
        - name: since
          in: query
          description: >-
            Only entries added at or after this time, oldest first. Inclusive —
            dedupe by `id`.
          schema:
            type: string
            format: date-time
          example: '2026-10-19T00:00:00Z'
        - name: phone
          in: query
          description: Check one number (any common format). Adds `listed` to the response.
          schema:
            type: string
          example: '+15550100777'
        - name: email
          in: query
          description: Check one email (case-insensitive). Adds `listed` to the response.
          schema:
            type: string
        - name: search
          in: query
          description: Substring match on phone or email
          schema:
            type: string
        - name: page
          in: query
          schema:
            type: integer
            default: 1
            minimum: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            minimum: 1
            maximum: 200
      responses:
        '200':
          description: Entries
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListDncResponse'
              example:
                entries:
                  - id: 6ad5ffeb89a6125f30a7dd2c
                    phone: '+15550100777'
                    email: null
                    reason: opt-out
                    addedBy: system
                    addedAt: '2026-10-19T11:32:59.433Z'
                    source: keyword-STOP
                total: 1
                page: 1
                limit: 50
                totalPages: 1
                hasMore: false
                listed: true
        '400':
          description: '`since` is not a valid date'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: since must be an ISO 8601 date, e.g. 2026-10-19T00:00:00Z
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: Unauthorized
        '429':
          description: Rate limit exceeded (120/min per workspace)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: Rate limit exceeded
components:
  schemas:
    ListDncResponse:
      type: object
      required:
        - entries
        - total
        - page
        - limit
        - totalPages
        - hasMore
      properties:
        entries:
          type: array
          items:
            $ref: '#/components/schemas/DncEntry'
        total:
          type: integer
        page:
          type: integer
        limit:
          type: integer
        totalPages:
          type: integer
        hasMore:
          type: boolean
          description: '`true` when another page exists'
        listed:
          type: boolean
          description: >-
            Only when `phone` or `email` is passed: whether that contact is on
            the list
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: string
        code:
          type: string
        reason:
          type: string
    DncEntry:
      type: object
      required:
        - id
        - reason
        - addedAt
      properties:
        id:
          type: string
          description: Entry id. Same as `data.dnc.id` in the `dnc.added` webhook.
        phone:
          type:
            - string
            - 'null'
          description: E.164 phone number
        email:
          type:
            - string
            - 'null'
          description: Lower-case email
        reason:
          type: string
          description: >-
            `opt-out` for an opt-out reply, otherwise the reason given when
            added
        addedBy:
          type: string
          description: '`system` for automatic opt-outs, otherwise a user id'
        addedAt:
          type: string
          format: date-time
          description: When it was added (UTC). Use as your `since` cursor.
        source:
          type:
            - string
            - 'null'
          description: >-
            `keyword-STOP` (or another keyword), `api`, `api-bulk`, `manual-ui`,
            `csv-import`, `list-import`, `tag-import`, or a CRM sync source
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: 'Workspace API key: Authorization: Bearer tuco_xxxxxxxxxxxxx'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.