Skip to content

DNC list

Manage the customer's Do-Not-Call (DNC) list: query, add/remove individual numbers, CSV bulk import, and CSV export. Every phone number is automatically normalised to E.164 (+84...) on the server.

Endpoint summary

EndpointPurpose
GET /api/telesales/dncList phone numbers on the DNC
POST /api/telesales/dncAdd one number to the DNC
DELETE /api/telesales/dnc/{phone}Remove one number from the DNC
POST /api/telesales/dnc/importBulk import from CSV (multipart)
GET /api/telesales/dnc/exportExport the full DNC as CSV

GET /api/telesales/dnc — list

Query parameters

FieldTypeRequiredDescriptionValid values
qstringoptionalSearch by phone number (LIKE %keyword%)
sourcestringoptionalFilter by sourcemanual / import / disposition / webhook
date_fromdatetimeoptionalFilter by added_at ≥ (ISO 8601 UTC)
date_todatetimeoptionalFilter by added_at ≤ (ISO 8601 UTC)
pageintegeroptionalPage number≥ 1 (default 1)
per_pageintegeroptionalRecords per page1-200 (default 50)

Response fields (each item in data[])

FieldTypeDescriptionValid values
phonestringOriginal phone number (format used on insert)
phone_e164stringNormalised E.164 number+84...
reasonstring|nullDNC reasonmax 500 chars
sourcestringSourcemanual / import / disposition / webhook
added_byinteger|nullUser ID who added (null if from webhook/system)
added_by_namestring|nullDisplay name of the adder
added_atdatetimeWhen it was added (ISO 8601 UTC)

Response 200:

json
{
  "data": [
    {
      "phone": "0900000000",
      "phone_e164": "+84900000000",
      "reason": "Customer opt-out",
      "source": "manual",
      "added_by": 7,
      "added_by_name": "Nguyen Van A",
      "added_at": "2026-04-01T03:00:00Z"
    }
  ],
  "meta": { "current_page": 1, "last_page": 3, "per_page": 50, "total": 124 }
}

POST /api/telesales/dnc — add one number

Request body fields

FieldTypeRequiredDescriptionValid values
phonestringPhone number — the server normalises to +84...0xxxxxxxxx or +84xxxxxxxxx
reasonstringoptionalDNC reasonmax 500 chars

Body:

json
{
  "phone": "0912345678",
  "reason": "Customer opt-out via inbound IVR"
}

Response body fields

FieldTypeDescriptionValid values
phonestringOriginal number from the POST
phone_e164stringNormalised number+84...
reasonstring|nullReason
sourcestringSource — always manual when created through this endpointmanual
added_byintegerUser ID of the creator
added_atdatetimeWhen it was added (ISO 8601 UTC)

Response 201:

json
{
  "data": {
    "phone": "0912345678",
    "phone_e164": "+84912345678",
    "reason": "Customer opt-out via inbound IVR",
    "source": "manual",
    "added_by": 7,
    "added_at": "2026-06-06T07:00:00Z"
  }
}

Response 422 — validation cases:

json
// Invalid phone format
{
  "message": "The given data was invalid.",
  "errors": { "phone": ["The phone format is invalid. Expected 0xxxxxxxxx or +84xxxxxxxxx."] }
}

// Already on DNC
{
  "message": "Phone number is already on the DNC list.",
  "errors": { "phone": ["Phone +84912345678 already in DNC since 2026-05-01."] }
}

DELETE /api/telesales/dnc/{phone}

{phone} accepts both 0xxxxxxxxx and +84xxxxxxxxx (the server normalises).

Response 204 No Content (success).

Response 404 — number not in the DNC:

json
{ "message": "Phone +84912345678 not found in DNC." }

POST /api/telesales/dnc/import — bulk CSV

Request: multipart/form-data

FieldDescription
fileCSV file (UTF-8). Required column: phone. Optional column: reason.
dedupeskip (default — skip rows that already exist) | update (overwrite reason)

Sample file:

csv
phone,reason
0912345678,Customer opt-out
0987654321,Wrong number

Response 200:

json
{
  "data": {
    "total_rows":   1500,
    "created":      1342,
    "skipped":      147,
    "errors":       11,
    "error_samples": [
      { "row": 23, "phone": "12345",       "error": "Invalid phone format" },
      { "row": 47, "phone": "0999999999",  "error": "Already exists" }
    ]
  }
}

Response 422 — cannot read the file:

json
{
  "message": "Unable to read the CSV file.",
  "errors": { "file": ["Missing required column: phone."] }
}

GET /api/telesales/dnc/export

Query params: same filter set as GET /api/telesales/dnc (q, source, date_from, date_to).

Response 200: text/csv — a streamed file with header Content-Disposition: attachment; filename="dnc-export-YYYYMMDD.csv". Columns: phone, phone_e164, reason, source, added_by_name, added_at.

Cấp phép theo điều khoản sử dụng của Zorio.