Skip to content

Suppression lists ​

8 endpoints. Every path below is relative to the API base URL and already includes the /api/v1 prefix — see conventions for authentication, pagination, errors and idempotency.

Endpoint
GET/suppression-listsList every suppression list in the organization by name with its entry count
POST/suppression-listsCreate a suppression list, deriving a unique URL-safe key from the name when none is supplied
GET/suppression-lists/{suppressionListId}Retrieve one suppression list with its type, campaign scope and entry count
PATCH/suppression-lists/{suppressionListId}Update a suppression list's name, description, type, campaign scope or enabled flag
DELETE/suppression-lists/{suppressionListId}Delete a suppression list and return an empty body
GET/suppression-lists/{suppressionListId}/entriesList a suppression list's numbers, optionally narrowed by a search substring match
POST/suppression-lists/{suppressionListId}/entriesAdd up to 10000 numbers in bulk, normalising to E.164 and reporting added, duplicate and invalid
DELETE/suppression-lists/{suppressionListId}/entries/{entry}Remove one number from a suppression list and refresh the list's entry count

Endpoints ​

List every suppression list in the organization by name with its entry count ​

GET/suppression-lists
  • Requires campaign.read.
  • Unpaginated and returns no meta block, unlike every other list endpoint in this API
bash
curl -X GET "$CALLAGENT_API_URL/suppression-lists" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Errors

StatusWhen it happens
403The API key does not carry the campaign.read scope

Example response, generated from the schema:

json
{
  "data": [
    "string"
  ]
}

Create a suppression list, deriving a unique URL-safe key from the name when none is supplied ​

POST/suppression-lists
  • Requires campaign.write.

Request body

FieldTypeRequiredNotes
namestringyesmax 255 chars
keystring | null—max 96 chars
descriptionstring | null—
typednc · opt_out · internal · imported · litigator · null | null—
applies_to_all_campaignsboolean | null—
bash
curl -X POST "$CALLAGENT_API_URL/suppression-lists" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "name": "Support Line",
       "type": "dnc",
       "applies_to_all_campaigns": true
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "name": "Support Line",
    "type": "dnc",
    "applies_to_all_campaigns": true
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'name' => 'Support Line',
    'type' => 'dnc',
    'applies_to_all_campaigns' => true,
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "name": "Support Line",
      "type": "dnc",
      "applies_to_all_campaigns": True
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
201data-wrapped object

Errors

StatusWhen it happens
403The API key does not carry the campaign.write scope
422Field validation failed

Example response, generated from the schema:

json
{
  "data": {
    "id": "01JQ0000000000000000000000",
    "name": "Support Line",
    "key": "string",
    "description": "string",
    "type": "string",
    "applies_to_all_campaigns": true,
    "enabled": true,
    "entries_count": 1
  }
}

Retrieve one suppression list with its type, campaign scope and entry count ​

GET/suppression-lists/{suppressionListId}
  • Requires campaign.read.

Path parameters

NameTypeRequiredNotes
suppressionListIdstringyes
bash
curl -X GET "$CALLAGENT_API_URL/suppression-lists/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists/01JQ0000000000000000000000`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
403The API key does not carry the campaign.read scope
404No suppression list with that id in this organization

Example response, generated from the schema:

json
{
  "data": {
    "id": "01JQ0000000000000000000000",
    "name": "Support Line",
    "key": "string",
    "description": "string",
    "type": "string",
    "applies_to_all_campaigns": true,
    "enabled": true,
    "entries_count": 1
  }
}

Update a suppression list's name, description, type, campaign scope or enabled flag ​

PATCH/suppression-lists/{suppressionListId}
  • Requires campaign.write.
  • The body is not validated, so this endpoint cannot return 422; an out-of-range type is written straight through

Path parameters

NameTypeRequiredNotes
suppressionListIdstringyes
bash
curl -X PATCH "$CALLAGENT_API_URL/suppression-lists/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists/01JQ0000000000000000000000`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'PATCH',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.patch(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped object

Errors

StatusWhen it happens
403The API key does not carry the campaign.write scope
404No suppression list with that id in this organization

Example response, generated from the schema:

json
{
  "data": {
    "id": "01JQ0000000000000000000000",
    "name": "Support Line",
    "key": "string",
    "description": "string",
    "type": "string",
    "applies_to_all_campaigns": true,
    "enabled": true,
    "entries_count": 1
  }
}

Delete a suppression list and return an empty body ​

DELETE/suppression-lists/{suppressionListId}
  • Requires campaign.write.
  • This response is not data-wrapped.
  • Deletes even when campaigns still reference the list in suppression_list_ids; no reference check is performed

Path parameters

NameTypeRequiredNotes
suppressionListIdstringyes
bash
curl -X DELETE "$CALLAGENT_API_URL/suppression-lists/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists/01JQ0000000000000000000000`, {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.delete(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
204No content

Errors

StatusWhen it happens
403The API key does not carry the campaign.write scope
404No suppression list with that id in this organization

List a suppression list's numbers, optionally narrowed by a search substring match ​

GET/suppression-lists/{suppressionListId}/entries
  • Requires campaign.read.
  • Page size comes from limit (default 50, max 500); meta carries only total, no page number

Path parameters

NameTypeRequiredNotes
suppressionListIdstringyes
bash
curl -X GET "$CALLAGENT_API_URL/suppression-lists/01JQ0000000000000000000000/entries" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists/01JQ0000000000000000000000/entries`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists/01JQ0000000000000000000000/entries');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists/01JQ0000000000000000000000/entries",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Errors

StatusWhen it happens
403The API key does not carry the campaign.read scope
404No suppression list with that id in this organization

Example response, generated from the schema:

json
{
  "data": [
    {
      "id": "01JQ0000000000000000000000",
      "phone_number": "+40712345678",
      "reason": "string",
      "source": "string",
      "expires_at": "2026-01-01T12:00:00+00:00"
    }
  ],
  "meta": {
    "total": 1
  }
}

Add up to 10000 numbers in bulk, normalising to E.164 and reporting added, duplicate and invalid ​

POST/suppression-lists/{suppressionListId}/entries
  • Requires campaign.write.
  • Un-normalisable numbers are returned verbatim in invalid rather than rejecting the request; re-adding an existing number counts as a duplicate

Path parameters

NameTypeRequiredNotes
suppressionListIdstringyes

Request body

FieldTypeRequiredNotes
numbersstring[]yesmin 1 items. max 10000 items
reasonstring | null—max 128 chars
sourcemanual · import · api · ivr_opt_out · call_opt_out · null | null—
expires_atstring | null—date-time
default_countrystring | null—max 8 chars
bash
curl -X POST "$CALLAGENT_API_URL/suppression-lists/01JQ0000000000000000000000/entries" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
       "numbers": [
         "string"
       ],
       "source": "manual",
       "expires_at": "2026-01-01T12:00:00+00:00"
     }'
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists/01JQ0000000000000000000000/entries`, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "numbers": [
      "string"
    ],
    "source": "manual",
    "expires_at": "2026-01-01T12:00:00+00:00"
  }),
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists/01JQ0000000000000000000000/entries');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
    'numbers' => [
        'string',
    ],
    'source' => 'manual',
    'expires_at' => '2026-01-01T12:00:00+00:00',
]),
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.post(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists/01JQ0000000000000000000000/entries",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    json={
      "numbers": [
        "string"
      ],
      "source": "manual",
      "expires_at": "2026-01-01T12:00:00+00:00"
    },
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
201data-wrapped object

Errors

StatusWhen it happens
403The API key does not carry the campaign.write scope
404No suppression list with that id in this organization
422Field validation failed on numbers, source or expires_at

Example response, generated from the schema:

json
{
  "data": {
    "added": 1,
    "duplicates": "string",
    "invalid": [
      "string"
    ]
  }
}

Remove one number from a suppression list and refresh the list's entry count ​

DELETE/suppression-lists/{suppressionListId}/entries/{entry}
  • Requires campaign.write.
  • This response is not data-wrapped.

Path parameters

NameTypeRequiredNotes
suppressionListIdstringyes
entrystringyes
bash
curl -X DELETE "$CALLAGENT_API_URL/suppression-lists/01JQ0000000000000000000000/entries/01JQ0000000000000000000000" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/suppression-lists/01JQ0000000000000000000000/entries/01JQ0000000000000000000000`, {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/suppression-lists/01JQ0000000000000000000000/entries/01JQ0000000000000000000000');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'DELETE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.delete(
    f"{os.environ['CALLAGENT_API_URL']}/suppression-lists/01JQ0000000000000000000000/entries/01JQ0000000000000000000000",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
204No content

Errors

StatusWhen it happens
403The API key does not carry the campaign.write scope
404No such suppression list, or no such entry on that list

Documented against the code. Anything not yet implemented is labelled, never described as working.