mySDRDocs

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).

POSThttps://mysdr.app/api/v1/exclusions
View Markdown

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

  • exclusions object[] · required — 1 to 500 items.
  • exclusions[].domain | email | company | linkedin_url string · 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[].type string — Default other. One of: customer, trial, test, former_customer, pipeline, unsubscribed, bounced, competitor, other.
  • exclusions[].reason string — Why, up to 500 characters.
  • exclusions[].source string — Where it came from, e.g. "CRM export".

Response

  • added integer · required — New exclusions.
  • updated integer · required — Exclusions that existed and got the new type and reason.
  • data object[] · required — The saved exclusions, as GET /exclusions gives them, each with marks: the rows it now marks as Do not contact (leads_total, companies_total, and up to 10 of each with id and name). A bounced address marks nothing.
  • warnings object[] — An address that marks no row: id, code (marks_no_row), message.
  • dashboard_url string · required — Companies in mySDR, filtered on Do not contact.

Credits

Free. This call never uses credits.

Errors

  • 400 invalid_request — No exclusions, 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"
}