Documentation menu

API reference

Domains

You send from your own domains. Add a domain, prove you own it with a TXT record, publish its SPF and DKIM records, and it is ready to send.

Every endpoint can also return the common errors listed in the overview, and all of them need a full-access key (a sending-access key gets 401 restricted_api_key). For the DNS steps in detail see Domains and DNS.

Libraries and CLI
Endpoint Node.js Python CLI
GET /domainsdomains.listdomains.listtsmart domains list
POST /domainsdomains.createdomains.createtsmart domains create
GET /domains/{id}domains.getdomains.gettsmart domains get
PATCH /domains/{id}domains.updatedomains.updatetsmart domains tracking
DELETE /domains/{id}domains.removedomains.removetsmart domains delete
POST /domains/{id}/verifydomains.verifydomains.verifytsmart domains verify

The domain object

Name Type Description
object string Always "domain".
id string Domain id (UUID).
name string The domain name, lowercase.
status string not_started: ownership not proven and not checked yet. pending: waiting for DNS records. partially_verified: some of the sending records (SPF, DKIM) were found at the last check. verified: SPF and DKIM were found at the last check and the domain can send.
created_at string When the domain was added.
region string Where mail is processed: "eu-central".
capabilities object sending: "enabled" once ownership is proven, else "disabled". receiving: "enabled" when the domain also receives mail in the company's mailboxes, else "disabled".
open_tracking boolean Single domain and create only. Whether HTML emails from this domain get an open-tracking pixel. Default false.
click_tracking boolean Single domain and create only. Whether links in HTML emails from this domain are tracked. Default false.
records object[] Single domain and create only. The DNS records to publish, see below.

Each entry of records:

Name Type Description
record string What the record is for: Ownership, SPF, DKIM, DMARC or MX.
name string The host name to publish the record at.
type string TXT or MX.
ttl string Always "Auto": use your DNS provider's default.
status string verified when the record was found with the expected value at the last check, else pending.
value string The value to publish. Empty while the DKIM key is being prepared.
priority integer MX records only.

Until ownership is proven, records holds only the Ownership TXT record. After that it lists SPF and DKIM (both needed to send), DMARC (recommended) and MX.

GET /domains

Lists the company's domains, newest first.

Permission: full access; the key's creator needs the API controls privilege.

Query

Name Type Description
limit integer 1 to 100, default 20.
after string A domain id: return older domains.
before string A domain id: return newer domains. Use either after or before.

Request

cURL
curl https://send.tsmart.ai/domains \
  -H "Authorization: Bearer $TSMART_API_KEY"

Response

List entries have no open_tracking, click_tracking or records.

200 OK
{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "object": "domain",
      "id": "a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d",
      "name": "yourdomain.com",
      "status": "verified",
      "created_at": "2026-10-09 08:15:02.123456+00",
      "region": "eu-central",
      "capabilities": { "sending": "enabled", "receiving": "disabled" }
    }
  ]
}

Errors

StatusNameWhen
403invalid_permissionThe key's creator lacks the API controls privilege.
422validation_errorlimit out of range, both after and before, or an invalid cursor.

POST /domains

Adds a domain and returns the TXT record that proves you own it.

Permission: full access; the key's creator needs the Domains privilege.

Body

Name Type Description
name required string The domain, such as yourdomain.com or mail.yourdomain.com. It is lowercased, and a pasted scheme, path, port, trailing dot or user@ part is removed.

Request

cURL
curl -X POST https://send.tsmart.ai/domains \
  -H "Authorization: Bearer $TSMART_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "yourdomain.com" }'
Node.js
const { data, error } = await tsmart.domains.create({ name: "yourdomain.com" });
Python
domain = client.domains.create({"name": "yourdomain.com"})

Response

200 OK
{
  "object": "domain",
  "id": "a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d",
  "name": "yourdomain.com",
  "status": "not_started",
  "created_at": "2026-10-12 09:30:11.402871+00",
  "region": "eu-central",
  "capabilities": { "sending": "disabled", "receiving": "disabled" },
  "open_tracking": false,
  "click_tracking": false,
  "records": [
    {
      "record": "Ownership",
      "name": "_tsmart-verify.yourdomain.com",
      "type": "TXT",
      "ttl": "Auto",
      "status": "pending",
      "value": "tsmart-verify=Qm8x2LkP0aZ7vB1nR4tYc9Wd"
    }
  ]
}

Publish the Ownership record, then call POST /domains/{id}/verify. A domain whose ownership is not proven within 7 days of when the company first added it expires and has to be added again; deleting and re-adding it does not restart the 7 days. A domain.created webhook event is sent.

Errors

StatusNameWhen
403invalid_permissionThe key's creator lacks the Domains privilege.
422missing_required_fieldname is missing or empty.
422validation_errorname is not a valid domain name.
403validation_error"This domain cannot be added": a public mailbox provider, an example domain or a platform domain. "The … domain has been registered already.": the domain is already in use. "The … domain has been added by another company that has not proven ownership yet …": another company's claim holds it; the message gives the time (UTC, ISO 8601) from which it can be added. "This company's claim of … expired …": your company's claim lapsed while another company was waiting for the domain; the message gives the time from which it can be added again. "The company's plan does not allow more domains".
403account_inactiveThe company's subscription is not active.
429validation_error10 domains of the company are already waiting for ownership verification.

GET /domains/{id}

Returns one domain with its status, tracking settings and DNS records.

Permission: full access; the key's creator needs the API controls privilege.

Path

Name Type Description
id required string The domain id.

Request

cURL
curl https://send.tsmart.ai/domains/a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer $TSMART_API_KEY"

Response

A domain whose ownership is proven, with SPF published and DKIM still missing:

200 OK
{
  "object": "domain",
  "id": "a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d",
  "name": "yourdomain.com",
  "status": "partially_verified",
  "created_at": "2026-10-12 09:30:11.402871+00",
  "region": "eu-central",
  "capabilities": { "sending": "enabled", "receiving": "disabled" },
  "open_tracking": false,
  "click_tracking": false,
  "records": [
    {
      "record": "SPF",
      "name": "yourdomain.com",
      "type": "TXT",
      "ttl": "Auto",
      "status": "verified",
      "value": "v=spf1 ip4:91.99.133.27 ~all"
    },
    {
      "record": "DKIM",
      "name": "ts2610._domainkey.yourdomain.com",
      "type": "TXT",
      "ttl": "Auto",
      "status": "pending",
      "value": "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
    },
    {
      "record": "DMARC",
      "name": "_dmarc.yourdomain.com",
      "type": "TXT",
      "ttl": "Auto",
      "status": "pending",
      "value": "v=DMARC1; p=none; rua=mailto:reports@system.tsmart.ai; fo=1"
    },
    {
      "record": "MX",
      "name": "yourdomain.com",
      "type": "MX",
      "ttl": "Auto",
      "status": "pending",
      "value": "mail.tsmart.ai.",
      "priority": 10
    }
  ]
}

The values above are examples: always publish the values from your own response. If your domain already has an SPF record, the SPF value is your record with the sending server added, so you keep one SPF record.

Errors

StatusNameWhen
403invalid_permissionThe key's creator lacks the API controls privilege.
404not_foundNo domain with this id in your company ("Domain not found").

PATCH /domains/{id}

Switches open and click tracking for emails sent from the domain.

Permission: full access; the key's creator needs the Domains privilege.

Path

Name Type Description
id required string The domain id.

Body

Name Type Description
open_tracking boolean Add a 1×1 tracking image to HTML emails, which records email.opened events.
click_tracking boolean Send links in HTML emails through https://send.tsmart.ai/t/c/…, which records email.clicked events and leads to the original URL for 180 days after the email was accepted.

Omitted fields keep their value; a body without either field changes nothing. Tracking applies to emails sent after the change, and only to their HTML part. Tracked links are signed: they can only lead to the URL your email contained. Links to your company's verified domains (and their subdomains) redirect at once; links to any other website first show a short page on send.tsmart.ai that names the destination, and the reader continues from there.

Request

cURL
curl -X PATCH https://send.tsmart.ai/domains/a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer $TSMART_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "open_tracking": true, "click_tracking": true }'

Response

200 OK
{
  "object": "domain",
  "id": "a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d"
}

A change sends a domain.updated webhook event.

Errors

StatusNameWhen
403invalid_permissionThe key's creator lacks the Domains privilege.
404not_foundNo domain with this id in your company.
422validation_erroropen_tracking or click_tracking is not a boolean.

DELETE /domains/{id}

Removes a domain from the company. Emails can no longer be sent from it.

Permission: full access; the key's creator must be the company owner.

Path

Name Type Description
id required string The domain id.

Request

cURL
curl -X DELETE https://send.tsmart.ai/domains/a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d \
  -H "Authorization: Bearer $TSMART_API_KEY"

Response

200 OK
{
  "object": "domain",
  "id": "a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d",
  "deleted": true
}

A domain.deleted webhook event is sent.

Errors

StatusNameWhen
403invalid_permissionThe key's creator is not the company owner.
404not_foundNo domain with this id in your company.
409resource_in_useThe domain still has mailboxes; remove them in the console first.

POST /domains/{id}/verify

Checks the domain's DNS: the first time it looks for the Ownership TXT record and, once found, sets the domain up for sending; after that it checks the SPF, DKIM, DMARC and MX records again.

Permission: full access; the key's creator needs the Domains privilege.

Path

Name Type Description
id required string The domain id.

Request

cURL
curl -X POST https://send.tsmart.ai/domains/a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d/verify \
  -H "Authorization: Bearer $TSMART_API_KEY"

Response

200 OK
{
  "object": "domain",
  "id": "a3b1c5d2-7e8f-4a6b-9c0d-1e2f3a4b5c6d"
}

The check runs during the call. Read the result with GET /domains/{id}: after ownership is proven, records lists the SPF and DKIM records to publish. Publish them and call verify again until status is verified. When the status changes, a domain.updated webhook event is sent.

Sending uses the stored result of the last check, not a live DNS lookup: after you publish or fix the records, call verify again before sending. The platform also re-checks verified domains periodically, so a record that is removed later changes the status and stops sending from the domain. Status changes found by this periodic check send no domain.updated event.

Errors

StatusNameWhen
403invalid_permissionThe key's creator lacks the Domains privilege.
404not_foundNo domain with this id in your company.
422validation_errorThe Ownership record was not found yet ("The TXT record _tsmart-verify.… was not found yet"), or the domain could not be set up for sending.