API reference
Add exclusions
Adds domains, addresses, company names or LinkedIn profiles nobody may contact, with their type and reason. One that exists gets the new type and reason. A bounce or unsubscribe you log with POST /outreach/activity is added by itself. For a person who opts out of every channel, add their linkedin_url (and their address if you have it): an address only marks a row that carries it. The response says which rows of Leads and Companies each exclusion now marks as Do not contact (marks), and warns when an address marks none (warnings).
Authentication
Send Authorization: Bearer gtk_…. Create the key under Connect assistant → API keys. Every gtk_ key can call these routes, also while the Signals API is closed. A missing, invalid or revoked key is 401.
Body parameters
exclusionsobject[]· required — 1 to 500 items.exclusions[].domain | email | company | linkedin_urlstring· required — Exactly one: a domain (acme.com; an address gives its domain), an address, a company name for when there is no domain, or one person’s LinkedIn profile URL.exclusions[].typestring— Defaultother. One of:customer,trial,test,former_customer,pipeline,unsubscribed,bounced,competitor,other.exclusions[].reasonstring— Why, up to 500 characters.exclusions[].sourcestring— Where it came from, e.g. "CRM export".
Response
addedinteger· required — New exclusions.updatedinteger· required — Exclusions that existed and got the new type and reason.dataobject[]· required — The saved exclusions, as GET /exclusions gives them, each withmarks: the rows it now marks as Do not contact (leads_total,companies_total, and up to 10 of each withidandname). A bounced address marks nothing.warningsobject[]— An address that marks no row:id,code(marks_no_row),message.dashboard_urlstring· required — Companies in mySDR, filtered on Do not contact.
Credits
Free. This call never uses credits.
Errors
- 400
invalid_request— Noexclusions, more than 500, an item with none or several of domain, email, company and linkedin_url, an unknown field or type, or a value that is not a domain, address, name or LinkedIn profile. - 401
authentication_error— The Authorization header is missing, or the key is unknown or revoked. - 403
permission_error— API access is not part of your plan, or your account is suspended. - 429
rate_limit_error— More than 60 requests per minute, or more than 3 at the same time, on one key. Wait for the Retry-After header. - 503
service_unavailable— The API is temporarily unavailable. Retry later. - 500
internal_error— Something went wrong on our side.
Example
cURL
curl -X POST "https://mysdr.app/api/v1/exclusions" \
-H "Authorization: Bearer $MYSDR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"exclusions": [
{
"domain": "customer.example",
"type": "customer",
"reason": "Customer since 2024"
},
{
"email": "test@beta.example",
"type": "test"
}
]
}'
JavaScript
const response = await fetch('https://mysdr.app/api/v1/exclusions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MYSDR_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
"exclusions": [
{
"domain": "customer.example",
"type": "customer",
"reason": "Customer since 2024"
},
{
"email": "test@beta.example",
"type": "test"
}
]
})
});
const body = await response.json();
Python
import json
import os
import urllib.request
payload = {
"exclusions": [
{
"domain": "customer.example",
"type": "customer",
"reason": "Customer since 2024"
},
{
"email": "test@beta.example",
"type": "test"
}
]
}
request = urllib.request.Request(
"https://mysdr.app/api/v1/exclusions",
headers={
"Authorization": f"Bearer {os.environ['MYSDR_API_KEY']}",
"Content-Type": "application/json"
},
data=json.dumps(payload).encode(),
method="POST",
)
with urllib.request.urlopen(request) as response:
body = json.load(response)
Example response
{
"added": 2,
"updated": 0,
"data": [
{
"id": "exc_9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"kind": "domain",
"value": "customer.example",
"label": "customer.example",
"type": "customer",
"reason": "Customer since 2024",
"source": null,
"created_at": "2026-10-23T09:00:00.000Z",
"marks": {
"leads_total": 1,
"companies_total": 1,
"leads": [
{
"id": "201",
"name": "Jane Doe"
}
],
"companies": [
{
"id": null,
"name": "Customer"
}
]
}
},
{
"id": "exc_1b2c3d4e-5f60-4a71-8b82-9c0d1e2f3a4b",
"kind": "email",
"value": "test@beta.example",
"label": "test@beta.example",
"type": "test",
"reason": null,
"source": null,
"created_at": "2026-10-23T09:00:00.000Z",
"marks": {
"leads_total": 0,
"companies_total": 0,
"leads": [],
"companies": []
}
}
],
"warnings": [
{
"id": "exc_1b2c3d4e-5f60-4a71-8b82-9c0d1e2f3a4b",
"code": "marks_no_row",
"message": "No row in Leads or Companies has test@beta.example, so no row is marked Do not contact. If the person is in Leads, add their LinkedIn profile as an exclusion too (linkedin_url), or put the address on their row with update_row (PATCH /tables/leads/{id})."
}
],
"dashboard_url": "https://mysdr.app/en/gtm/companies?excluded=1"
}