English
English
Appearance
English
English
Appearance
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 | Purpose |
|---|---|
GET /api/telesales/dnc | List phone numbers on the DNC |
POST /api/telesales/dnc | Add one number to the DNC |
DELETE /api/telesales/dnc/{phone} | Remove one number from the DNC |
POST /api/telesales/dnc/import | Bulk import from CSV (multipart) |
GET /api/telesales/dnc/export | Export the full DNC as CSV |
GET /api/telesales/dnc — list | Field | Type | Required | Description | Valid values |
|---|---|---|---|---|
q | string | optional | Search by phone number (LIKE %keyword%) | |
source | string | optional | Filter by source | manual / import / disposition / webhook |
date_from | datetime | optional | Filter by added_at ≥ (ISO 8601 UTC) | |
date_to | datetime | optional | Filter by added_at ≤ (ISO 8601 UTC) | |
page | integer | optional | Page number | ≥ 1 (default 1) |
per_page | integer | optional | Records per page | 1-200 (default 50) |
data[]) | Field | Type | Description | Valid values |
|---|---|---|---|
phone | string | Original phone number (format used on insert) | |
phone_e164 | string | Normalised E.164 number | +84... |
reason | string|null | DNC reason | max 500 chars |
source | string | Source | manual / import / disposition / webhook |
added_by | integer|null | User ID who added (null if from webhook/system) | |
added_by_name | string|null | Display name of the adder | |
added_at | datetime | When it was added (ISO 8601 UTC) |
Response 200:
{
"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 | Field | Type | Required | Description | Valid values |
|---|---|---|---|---|
phone | string | ✅ | Phone number — the server normalises to +84... | 0xxxxxxxxx or +84xxxxxxxxx |
reason | string | optional | DNC reason | max 500 chars |
Body:
{
"phone": "0912345678",
"reason": "Customer opt-out via inbound IVR"
}| Field | Type | Description | Valid values |
|---|---|---|---|
phone | string | Original number from the POST | |
phone_e164 | string | Normalised number | +84... |
reason | string|null | Reason | |
source | string | Source — always manual when created through this endpoint | manual |
added_by | integer | User ID of the creator | |
added_at | datetime | When it was added (ISO 8601 UTC) |
Response 201:
{
"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:
// 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:
{ "message": "Phone +84912345678 not found in DNC." }POST /api/telesales/dnc/import — bulk CSV Request: multipart/form-data
| Field | Description |
|---|---|
file | CSV file (UTF-8). Required column: phone. Optional column: reason. |
dedupe | skip (default — skip rows that already exist) | update (overwrite reason) |
Sample file:
phone,reason
0912345678,Customer opt-out
0987654321,Wrong numberResponse 200:
{
"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:
{
"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.