Sending

Domains & deliverability

Authenticate your own domain, then send from it.

Sendara sends all email through Amazon SES. When you add a domain, Sendara registers it with SES as its own verified identity. Sendara then starts DKIM signing, sets a custom MAIL FROM subdomain, and returns the 6 DNS records that you publish. Sendara records a bounce and a complaint against the domain, and it suppresses the recipient.

Every new account gets a sandbox domain (<account>.sandbox.sendara.dev) that is already fully verified. Use it to build against the API with no DNS work. Add your own domain to send real mail. An account holds up to 100 domains, counting every verification status.

Add a domain

Register the domain (or subdomain) you want to send from. The response is the full domain object, including the DNS records to publish and a per-record pending status. Requires a key with the admin scope.

add-domain.sh
curl https://api.sendara.dev/v1/domains \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "mail.acme.com" }'

The response carries everything you need to configure DNS:

{
  "id": "dom_1f8c0a2b3d4e5f60718293a4b5c6d7e8",
  "domain": "mail.acme.com",
  "dkim_status": "pending",
  "spf_status": "pending",
  "dmarc_status": "pending",
  "txt_status": "pending",
  "mail_from_domain": "mail.mail.acme.com",
  "dns_records": [
    { "type": "CNAME", "name": "abc123._domainkey.mail.acme.com", "value": "abc123.dkim.amazonses.com" },
    { "type": "CNAME", "name": "def456._domainkey.mail.acme.com", "value": "def456.dkim.amazonses.com" },
    { "type": "CNAME", "name": "ghi789._domainkey.mail.acme.com", "value": "ghi789.dkim.amazonses.com" },
    { "type": "MX",    "name": "mail.mail.acme.com",        "value": "10 feedback-smtp.us-east-1.amazonses.com" },
    { "type": "TXT",   "name": "mail.mail.acme.com",        "value": "v=spf1 include:amazonses.com ~all" },
    { "type": "TXT",   "name": "_dmarc.mail.acme.com",      "value": "v=DMARC1; p=none; rua=mailto:[email protected]" }
  ],
  "created_at": "2026-06-14T09:00:00Z",
  "updated_at": "2026-06-14T09:00:00Z"
}
Send from a subdomain such as mail.acme.com, not from the root acme.com. A subdomain keeps the custom MAIL FROM record and the DMARC record out of your apex zone.

DNS records

A custom domain returns 6 records: 3 DKIM CNAMEs for signing, an MX record and a TXT record for the custom MAIL FROM, and a TXT record for DMARC. Publish all 6 exactly as the API returns them. The names and the values below are examples. Your DKIM tokens and your region differ, and the shape does not.

PurposeTypeName / HostValue
DKIM 1CNAMEabc123._domainkey.mail.acme.comabc123.dkim.amazonses.com
DKIM 2CNAMEdef456._domainkey.mail.acme.comdef456.dkim.amazonses.com
DKIM 3CNAMEghi789._domainkey.mail.acme.comghi789.dkim.amazonses.com
MAIL FROM (MX)MXmail.mail.acme.com10 feedback-smtp.us-east-1.amazonses.com
MAIL FROM (SPF)TXTmail.mail.acme.comv=spf1 include:amazonses.com ~all
DMARCTXT_dmarc.mail.acme.comv=DMARC1; p=none; rua=mailto:[email protected]

What each record does:

  • DKIM. 3 CNAMEs delegate the signing to Amazon SES. A receiver uses them to verify that nobody altered your mail in transit. All 3 must resolve before DKIM passes.
  • MAIL FROM (MX + SPF). Sendara sets a custom return-path subdomain (mail.<your-domain>). The MX record routes a bounce notification back to Amazon SES. The SPF TXT record authorizes Amazon SES to send for that subdomain. The 2 records align SPF with your domain, and DMARC then passes on SPF.
  • DMARC. Sendara generates a starter policy TXT record at _dmarc.<your-domain>. The record is p=none. It tells a receiver where to send an aggregate report, and it does not ask the receiver to reject anything. You own the policy after you publish it.

Each record object in the API response has this shape:

typestringRequired
DNS record type: CNAME, MX, or TXT.
namestringRequired
The hostname to create the record at. Some providers want this relative to the zone. Drop the trailing domain if yours auto-appends it.
valuestringRequired
The exact value to publish. For MX, the leading number is the priority. Enter it in your provider's priority field if it has one.
Do not add a second SPF TXT record at your root domain for Sendara. SPF allows only one v=spf1 record per hostname. A duplicate causes a permerrorand breaks authentication. The custom MAIL FROM keeps Sendara's SPF on its own subdomain, so your existing root SPF is untouched.

Notes on your DNS provider

  • Some DNS forms append the zone for you. If your provider already shows .acme.com next to the input, enter only the host part (abc123._domainkey.mail), not the fully qualified name.
  • For the MX record, the value 10 feedback-smtp... holds the priority 10 and the target. If your provider has a separate priority field, put 10 in that field. Put the hostname in the value field.
  • A CNAME value must point at the Amazon SES host exactly. Do not add a trailing comment. Do not wrap the value in quotation marks. Your provider can add quotation marks around a TXT value, which is correct.

DNS guidance for your provider

Call GET /v1/domains/{domain}/dns-setup to get the host format that your provider wants. Sendara detects the DNS provider from the nameservers. For each record it returns the host relative to your zone apex, and a dashboard_url link to the settings page of that provider. The DNS guide in the dashboard reads this endpoint.

curl https://api.sendara.dev/v1/domains/mail.acme.com/dns-setup \
  -H "Authorization: Bearer sk_live_xxx"
{
  "domain": "mail.acme.com",
  "zone_apex": "acme.com",
  "provider": {
    "id": "cloudflare",
    "name": "Cloudflare",
    "supports_api": true,
    "unproxy_hint": true,
    "dashboard_url": "https://dash.cloudflare.com/?to=/:account/:zone/dns",
    "record_name_label": "Name",
    "record_value_label": "Content"
  },
  "records": [
    { "type": "CNAME", "name": "abc123._domainkey.mail.acme.com",
      "host": "abc123._domainkey.mail", "value": "abc123.dkim.amazonses.com" },
    { "type": "CNAME", "name": "def456._domainkey.mail.acme.com",
      "host": "def456._domainkey.mail", "value": "def456.dkim.amazonses.com" },
    { "type": "CNAME", "name": "ghi789._domainkey.mail.acme.com",
      "host": "ghi789._domainkey.mail", "value": "ghi789.dkim.amazonses.com" },
    { "type": "MX", "name": "mail.mail.acme.com",
      "host": "mail.mail", "value": "10 feedback-smtp.us-east-1.amazonses.com" },
    { "type": "TXT", "name": "mail.mail.acme.com",
      "host": "mail.mail", "value": "v=spf1 include:amazonses.com ~all" },
    { "type": "TXT", "name": "_dmarc.mail.acme.com",
      "host": "_dmarc.mail", "value": "v=DMARC1; p=none; rua=mailto:[email protected]" }
  ],
  "mail_from_domain": "mail.mail.acme.com",
  "dkim_status": "pending",
  "spf_status": "pending",
  "dmarc_status": "pending",
  "txt_status": "pending"
}

The host field is the name without your zone apex. A provider that wants a relative host (GoDaddy, Namecheap or Porkbun) expects this value in its Name or Host field. A provider that wants the fully qualified name reads name instead. The record_name_label field and the record_value_label field give the name that the provider prints on each input.

To import all 6 records at once, call GET /v1/domains/{domain}/dns-setup/zonefile. It returns the same records as a BIND-format fragment. Paste the fragment into your zone file, or import the file.

curl https://api.sendara.dev/v1/domains/mail.acme.com/dns-setup/zonefile \
  -H "Authorization: Bearer sk_live_xxx" \
  -o mail.acme.com.zone.txt

Both endpoints are read-only and take a read scope.

Verify & re-verify

Publish the records, then start a check. Sendara reads DNS again, and it reads the identity status from Amazon SES. Sendara returns one result for each record. A record has the status pending, verified or failed. Sendara sets fully_verified to true only after DKIM, SPF, the MAIL FROM record and DMARC all pass.

verify.sh
curl -X POST \
  https://api.sendara.dev/v1/domains/mail.acme.com/verify \
  -H "Authorization: Bearer sk_live_xxx"

A partial result is normal while DNS propagates. DKIM can verify before DMARC does:

{
  "domain": "mail.acme.com",
  "fully_verified": false,
  "results": [
    { "field": "dkim_status",  "type": "CNAME", "name": "abc123._domainkey.mail.acme.com", "status": "verified" },
    { "field": "dkim_status",  "type": "CNAME", "name": "def456._domainkey.mail.acme.com", "status": "verified" },
    { "field": "dkim_status",  "type": "CNAME", "name": "ghi789._domainkey.mail.acme.com", "status": "verified" },
    { "field": "txt_status",   "type": "MX",    "name": "mail.mail.acme.com",   "status": "verified" },
    { "field": "spf_status",   "type": "TXT",   "name": "mail.mail.acme.com",   "status": "verified" },
    { "field": "dmarc_status", "type": "TXT",   "name": "_dmarc.mail.acme.com", "status": "pending",
      "detail": "no _dmarc TXT record found yet" }
  ]
}

Verification is idempotent, so you can repeat the call. The time to propagate depends on your DNS provider and on your TTL values. Sendara also re-checks every domain that is still pending. The check runs every 10 minutes. Sendara emails you at your account address when a domain becomes fully verified.

Until a domain is fully verified, a send from an address on it returns 422 from_not_verified. The fix is to finish publishing the records and re-verify, or send from the shared sender meanwhile (see below).

Delete a domain

Call DELETE /v1/domains/{domain} to remove a sending domain. Sendara deletes the domain and its dependent rows. Sendara then deletes the Amazon SES identity. That last step is best-effort, so an identity that stays behind never blocks the removal. A successful call returns 204 No Content. The call needs an admin key.

curl -X DELETE https://api.sendara.dev/v1/domains/mail.acme.com \
  -H "Authorization: Bearer sk_live_admin_xxx"
You cannot delete the sandbox domain. A delete call against it returns 422 cannot_delete_sandbox. The sandbox domain costs nothing, and it stays available for the life of the account.

The shared sender and your own domain

You can send before you verify a domain. Sendara has two modes.

  • The shared sender. Omit from_email. Sendara then sends from a platform address on a domain that is already verified. An account without a verified domain can send only to its own account email in this mode. Use it to connect your integration and to see your first delivery.
  • Your own verified domain. After a domain is fully verified, set from_email to any address on it, and send to any recipient. Use this mode for production traffic. Your domain carries the DKIM signature and the DMARC alignment.

Default sender name

Give a verified domain a default sender name with PUT /v1/domains/{domain}/from-name, or in the dashboard (Domains → your domain → Default sender name). Every send from that domain then shows the name in recipients' inboxes, for example Acme <[email protected]> instead of the bare address. A per-send display name on from_email (the name first, then the address in angle brackets) overrides the default for that message.

To send real mail to your own addresses before you go live, register and verify up to 3 test recipients. Then set test_send: true on the send. Each test recipient accepts 10 test sends per day. See Test your integration for the flow.

What Sendara does not do

Sendara sends every message through the shared Amazon SES infrastructure. Read these limits before you plan a large send.

  • We do not offer a dedicated IP, and we do not run a warmup schedule.
  • No provider can promise inbox placement, because placement depends on your content and your recipients. Sendara reports the delivery events that Amazon SES returns. It does not measure which folder holds the message.
  • Sendara generates a starter DMARC record at p=none, and it checks that a policy is present. You choose the policy, and you read your own aggregate reports.
  • Amazon SES rewrites a tracked link to the awstrack.me domain so that it can record the click. A branded tracking domain is not available.

Bounce and complaint rates

Sendara computes a bounce rate and a complaint rate for your account from message events. Sendara marks the account when a rate crosses one of these thresholds.

  • A complaint rate above 0.1% sets the health to critical. Stop sending and verify your recipient data.
  • A bounce rate above 5% sets the health to warning. A bounce rate above 2% also sets it to warning. A complaint rate above 0.1% wins over both, and the health stays critical.

The health field holds one of 3 values: good, warning, or critical. Sendara divides each rate by the number of sent messages.

Sendara adds a hard bounce and every complaint to your suppression list, so a second send to that address never leaves the API. Sendara

Your DMARC record starts at p=none. Confirm that your own mail passes DKIM and SPF, then tighten the policy yourself. Move it to p=quarantine, and then to p=reject, to stop another sender from spoofing your domain.

A DMARC policy at p=quarantine or p=reject is a precondition for BIMI, which shows your brand logo as the sender avatar. See BIMI / brand logo to upload a logo and to publish the record.

Suppressions

Sendara adds a hard bounce and every complaint to your suppression list. A later send to that recipient returns 409 recipient_suppressed. You do no work to get this behaviour.

You can also manage the list yourself:

curl https://api.sendara.dev/v1/suppressions \
  -H "Authorization: Bearer sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "channel": "email", "recipient": "[email protected]", "reason": "hard_bounce" }'

The deliverability checklist

  • Publish all 6 records, and confirm that DKIM, SPF and DMARC align.
  • Send transactional email from a dedicated subdomain.
  • Send only to a recipient who asked for your mail.
  • Never send again to a suppressed address.
  • Read your events. A rise in the bounce rate or in the complaint rate is an early signal. Read the DMARC aggregate reports in your rua mailbox to find an authentication failure.

Common questions

How many DNS records do I publish?
Six. Three DKIM CNAME records sign your mail. One MX record and one SPF TXT record serve the custom MAIL FROM subdomain. One DMARC TXT record carries the starter policy.
My SPF record is correct, so why is spf_status still failed?
Sendara publishes SPF on the mail. subdomain, and not on your apex. A correct record at the apex does not verify, because Sendara does not read the apex. Publish v=spf1 include:amazonses.com ~all at mail.<your-domain>, beside the MX record.
Where does a DKIM CNAME point?
Each DKIM CNAME points at <token>.dkim.amazonses.com. It never points at a Sendara host. The usual failure is a DNS form that appends your zone twice, which produces token._domainkey.example.com.example.com.
How long does the verification take?
Sendara re-checks every domain that is still pending, once every 10 minutes. DNS propagation commonly takes from 15 to 60 minutes, and it can take up to 48 hours. Sendara emails your account address when the domain becomes fully verified.
How many domains can one account hold?
Up to 100 sending domains, counted at every status rather than only the verified ones. The next one returns 403 domain_limit_reached. Delete a domain that you no longer send from before adding another.