Skip to content

Sender Domains API

Sender domains control which email addresses your workspace can send from. Verifying your own domain is optional — every workspace can send (in both test and live mode) from Synapse's shared, already-verified pyrx.tech domain with no setup. To send from your own domain instead, add it and verify ownership by configuring DNS records (SPF, DKIM, and DMARC). A verified custom domain improves deliverability, isolates your sender reputation, and puts your brand in the "From" address. This API manages those custom domains; it is not a prerequisite for sending.

When you add a domain, Synapse automatically detects the DNS provider from NS records and returns it in the dns_provider field. For providers that support Domain Connect (currently Cloudflare), you can use the Domain Connect endpoints to configure DNS records automatically.

Note

For a user guide on configuring sender domains in the dashboard, see Sender Domain Setup.


Endpoints

MethodPathDescription
GET/v1/workspace/domainsList sender domains
GET/v1/workspace/domains/{domain_id}Get domain detail with DNS records and provider detection
POST/v1/workspace/domainsAdd a new sender domain
POST/v1/workspace/domains/{domain_id}/verifyTrigger DNS verification
GET/v1/workspace/domains/{domain_id}/domain-connect/discoverDiscover Domain Connect support for a domain
GET/v1/workspace/domains/{domain_id}/domain-connectGet signed Domain Connect apply URL
GET/v1/workspace/domains/domain-connect/callbackHandle redirect after Domain Connect authorization
POST/v1/workspace/domains/{domain_id}/domain-connect/resetReset a failed Domain Connect flow
DELETE/v1/workspace/domains/{domain_id}Delete a sender domain

List Domains

Returns all sender domains configured for the current workspace.

bash
curl https://synapse-api.pyrx.tech/v1/workspace/domains \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:read permission.

Response

json
{
"domains": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"domain": "mail.acme.com",
"status": "verified",
"dns_records": {
"records": [
{
"type": "CNAME",
"host": "resend._domainkey.mail.acme.com",
"value": "resend.domainkey.resend.dev",
"purpose": "DKIM",
"verified": true
}
]
},
"is_cloudflare": false,
"dns_provider": "namecheap",
"dc_provider": null,
"dc_flow_state": null,
"created_at": "2026-02-01T10:00:00Z",
"verified_at": "2026-02-01T12:30:00Z"
},
{
"id": "b2c3d4e5-f678-9012-abcd-ef1234567890",
"domain": "notifications.acme.com",
"status": "pending",
"dns_records": {
"records": []
},
"is_cloudflare": true,
"dns_provider": "cloudflare",
"dc_provider": "Cloudflare",
"dc_flow_state": "applied",
"created_at": "2026-04-20T14:00:00Z",
"verified_at": null
}
],
"total": 2
}

Response Fields

FieldTypeDescription
dns_providerstring or nullDetected DNS provider identifier. One of: cloudflare, namecheap, godaddy, route53, google, digitalocean, ns1, hetzner, vultr, linode, hover, dnsimple, dyn, vercel, wordpress, other, or null if not yet detected.
is_cloudflarebooleanWhether the domain uses Cloudflare nameservers.
dc_providerstring or nullDomain Connect provider name (e.g., "Cloudflare"), set after discovery.
dc_flow_statestring or nullCurrent Domain Connect flow state. See Domain Connect Flow States.

Get Domain Detail

Returns detailed domain information including individual DNS record verification status, DNS provider detection, and Domain Connect availability.

bash
curl https://synapse-api.pyrx.tech/v1/workspace/domains/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:read permission.

Response

json
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"domain": "mail.acme.com",
"status": "verified",
"dns_records": [
{
"type": "TXT",
"host": "mail.acme.com",
"name": "@",
"value": "v=spf1 include:send.resend.dev ~all",
"purpose": "SPF",
"verified": true
},
{
"type": "CNAME",
"host": "resend._domainkey.mail.acme.com",
"name": "resend._domainkey",
"value": "resend.domainkey.resend.dev",
"purpose": "DKIM",
"verified": true
},
{
"type": "TXT",
"host": "_dmarc.mail.acme.com",
"name": "_dmarc",
"value": "v=DMARC1; p=none;",
"purpose": "DMARC",
"verified": true
}
],
"is_cloudflare": false,
"dns_provider": "namecheap",
"dc_provider": null,
"dc_flow_state": null,
"dc_applied_at": null,
"dc_available": false,
"created_at": "2026-02-01T10:00:00Z",
"verified_at": "2026-02-01T12:30:00Z",
"dns_verified_at": "2026-02-01T12:30:00Z"
}

Response Fields

The detail response extends the list response with additional fields:

FieldTypeDescription
dns_recordsarrayFlattened list of DNS records with individual verified status. Each record includes type, host, name (provider-friendly label), value, purpose, and verified.
dns_providerstring or nullDetected DNS provider identifier. Detected on first access if not already set.
is_cloudflarebooleanWhether the domain uses Cloudflare nameservers.
dc_availablebooleanWhether Domain Connect auto-configuration is available for this domain. true when the domain's DNS provider supports Domain Connect and the server has Domain Connect configured.
dc_providerstring or nullDomain Connect provider display name (e.g., "Cloudflare").
dc_flow_statestring or nullCurrent Domain Connect flow state. See Domain Connect Flow States.
dc_applied_atdatetime or nullWhen Domain Connect records were last applied.
dns_verified_atdatetime or nullWhen DNS records were last verified.
Note

The dns_provider field is detected automatically when you first access the domain detail. The detection result is cached on the domain record. The dns_records array in the detail response is flattened (a list of record objects), while in the list response it uses the raw JSONB structure with a records wrapper.


Add a Domain

Registers a new sender domain and generates the DNS records you need to configure for verification.

bash
curl -X POST https://synapse-api.pyrx.tech/v1/workspace/domains \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"domain": "mail.acme.com"
}'

Auth: JWT (dashboard). Requires domains:write permission.

Request Body

FieldTypeRequiredDescription
domainstringYesThe domain to add (4-255 characters, valid domain format, e.g., mail.acme.com)
Tip

Use a subdomain like mail.acme.com or notifications.acme.com rather than your root domain. This isolates email sending reputation and avoids conflicts with existing DNS records.

Response (201 Created)

json
{
"id": "c3d4e5f6-7890-1234-abcd-ef1234567890",
"domain": "mail.acme.com",
"status": "pending",
"dns_records": {
"records": [
{
"type": "TXT",
"host": "mail.acme.com",
"value": "v=spf1 include:send.resend.dev ~all",
"purpose": "SPF"
},
{
"type": "CNAME",
"host": "resend._domainkey.mail.acme.com",
"value": "resend.domainkey.resend.dev",
"purpose": "DKIM"
},
{
"type": "TXT",
"host": "_dmarc.mail.acme.com",
"value": "v=DMARC1; p=none;",
"purpose": "DMARC"
}
]
},
"is_cloudflare": false,
"dns_provider": null,
"dc_provider": null,
"dc_flow_state": null,
"created_at": "2026-04-25T09:00:00Z",
"verified_at": null
}

After adding the domain, configure the DNS records shown in the response with your DNS provider, then call the verify endpoint. Alternatively, use the Domain Connect discover endpoint to check if auto-configuration is available.

Error: Duplicate Domain (409 Conflict)

json
{
"detail": "Domain already exists in this workspace"
}

Verify Domain DNS

Triggers a DNS verification check for a domain. Synapse queries your DNS records and updates the verification status for each record. Call this after configuring the DNS records returned by the create endpoint.

bash
curl -X POST https://synapse-api.pyrx.tech/v1/workspace/domains/c3d4e5f6-7890-1234-abcd-ef1234567890/verify \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:write permission.

Response (200 OK)

When all DNS records are verified:

json
{
"id": "c3d4e5f6-7890-1234-abcd-ef1234567890",
"domain": "mail.acme.com",
"status": "verified",
"dns_records": {
"records": [
{
"type": "CNAME",
"host": "resend._domainkey.mail.acme.com",
"value": "resend.domainkey.resend.dev",
"purpose": "DKIM",
"verified": true
}
]
},
"created_at": "2026-04-25T09:00:00Z",
"verified_at": "2026-04-25T09:15:00Z"
}

When verification is still pending (DNS records not yet propagated):

json
{
"id": "c3d4e5f6-7890-1234-abcd-ef1234567890",
"domain": "mail.acme.com",
"status": "pending",
"dns_records": {
"records": [
{
"type": "CNAME",
"host": "resend._domainkey.mail.acme.com",
"value": "resend.domainkey.resend.dev",
"purpose": "DKIM",
"verified": false
}
]
},
"created_at": "2026-04-25T09:00:00Z",
"verified_at": null
}
Note

DNS propagation can take up to 48 hours, though most records propagate within minutes. If verification fails, double-check that your CNAME records match the values exactly -- including trailing dots if your DNS provider requires them.

Error: Domain Not Found (404)

json
{
"detail": "Domain not found"
}

Domain Connect

Domain Connect is an open protocol that allows one-click DNS configuration. Instead of manually copying DNS records into your provider's dashboard, Domain Connect redirects you to your DNS provider's authorization page where you approve the changes in one click.

Synapse currently supports Domain Connect for domains hosted on Cloudflare. Support for additional providers that implement the Domain Connect protocol will be added over time.

Domain Connect Flow States

The dc_flow_state field on a domain tracks where it is in the Domain Connect flow:

StateMeaning
nullDomain Connect has not been initiated
discoveryDiscovery completed -- provider supports Domain Connect
pending_consentUser has been redirected to the DNS provider for authorization
appliedDNS records were applied successfully by the provider
failedAuthorization was cancelled or an error occurred

Typical Flow

  1. Discover: Call the discover endpoint to check if the domain's provider supports Domain Connect.
  2. Get apply URL: Call the Domain Connect URL endpoint to get a signed URL.
  3. Redirect: Redirect the user's browser to the apply URL.
  4. Callback: The DNS provider redirects back to the callback endpoint after authorization.
  5. Auto-verify: The callback endpoint triggers DNS verification automatically.

Discover Domain Connect Support

Checks whether the domain's DNS provider supports Domain Connect. Performs DNS discovery (queries _domainconnect TXT record) and returns availability along with a signed apply URL if supported.

Discovery results are cached for 7 days. Pass force=true to re-run discovery regardless of cache age.

If the domain's dc_flow_state is "failed", this endpoint resets it so the user can retry the flow.

bash
curl https://synapse-api.pyrx.tech/v1/workspace/domains/c3d4e5f6-7890-1234-abcd-ef1234567890/domain-connect/discover \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:write permission.

Query Parameters

ParameterTypeDefaultDescription
forcebooleanfalseForce re-discovery even if cached result is fresh (less than 7 days old)

Response: Available (200 OK)

json
{
"available": true,
"provider_name": "Cloudflare",
"provider_id": "cloudflare",
"apply_url": "https://dash.cloudflare.com/cdn-cgi/access/domain-connect/v2/domainTemplates/providers/..."
}
FieldTypeDescription
availablebooleanWhether Domain Connect is supported for this domain
provider_namestring or nullDisplay name of the Domain Connect provider (e.g., "Cloudflare")
provider_idstring or nullProvider identifier from the Domain Connect settings endpoint
apply_urlstring or nullSigned URL to redirect the user to for DNS authorization. Includes all required DNS record templates and a redirect URI back to the dashboard.

Response: Not Available (200 OK)

json
{
"available": false,
"provider_name": null,
"provider_id": null,
"apply_url": null
}

Returned when the domain's DNS provider does not support Domain Connect, or when Domain Connect is not configured on the server.

Error: Domain Not Found (404)

json
{
"detail": "Domain not found"
}

Get Domain Connect URL

Returns a signed Domain Connect apply URL for one-click DNS setup. Uses cached discovery data if available and fresh; otherwise runs discovery first.

This endpoint sets dc_flow_state to "pending_consent", indicating the user is about to be redirected to the DNS provider.

bash
curl https://synapse-api.pyrx.tech/v1/workspace/domains/c3d4e5f6-7890-1234-abcd-ef1234567890/domain-connect \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:write permission.

Response (200 OK)

json
{
"url": "https://dash.cloudflare.com/cdn-cgi/access/domain-connect/v2/domainTemplates/providers/.../apply?domain=mail.acme.com&...",
"provider": "Cloudflare"
}
FieldTypeDescription
urlstringSigned Domain Connect apply URL. Redirect the user's browser to this URL.
providerstring or nullDisplay name of the DNS provider.

Redirect the user to the returned url. After they authorize the DNS changes, their browser is redirected back to the dashboard callback page, which calls the callback endpoint to complete the flow.

Error: Not Configured (501 Not Implemented)

json
{
"detail": "Domain Connect is not configured on this server"
}

Error: Provider Not Supported (422 Unprocessable Entity)

json
{
"detail": "Domain Connect is not supported by this domain's DNS provider"
}

Error: Domain Not Found (404)

json
{
"detail": "Domain not found"
}

Domain Connect Callback

Handles the redirect from the DNS provider after the user authorizes (or cancels) the Domain Connect flow. This endpoint is called by the dashboard's callback page, not directly by API consumers.

GET /v1/workspace/domains/domain-connect/callback?domain_id={domain_id}&status=success

Auth: JWT (dashboard). Requires domains:write permission.

Query Parameters

ParameterTypeRequiredDescription
domain_idUUIDYesThe domain ID passed through the redirect
statusstringNoStatus from the DNS provider (e.g., "success")
errorstringNoError message from the DNS provider, if authorization was cancelled or failed

Behavior

  • Validates that dc_flow_state is "pending_consent" (prevents replay attacks).
  • On success: sets dc_flow_state to "applied", records dc_applied_at, and triggers DNS verification with retry (to allow for propagation delay).
  • On error: sets dc_flow_state to "failed".

Response (200 OK)

Returns a DomainResponse with the updated domain state.

Error: Invalid Flow State (409 Conflict)

json
{
"detail": "Invalid Domain Connect flow state: expected 'pending_consent', got 'applied'"
}

Reset Domain Connect State

Resets a failed or stuck Domain Connect flow so the user can retry. Clears dc_flow_state back to null and invalidates the cached discovery data so the next discover call runs fresh.

bash
curl -X POST https://synapse-api.pyrx.tech/v1/workspace/domains/c3d4e5f6-7890-1234-abcd-ef1234567890/domain-connect/reset \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:write permission.

Response (200 OK)

Returns a DomainResponse with dc_flow_state set to null.

Error: Invalid State (409 Conflict)

Can only reset from "failed" or "pending_consent" states:

json
{
"detail": "Cannot reset Domain Connect state: current state is 'applied', expected 'failed' or 'pending_consent'"
}

Error: Domain Not Found (404)

json
{
"detail": "Domain not found"
}

Delete a Domain

Permanently removes a sender domain from the workspace. Any email templates or flows referencing this domain's sender address will need to be updated.

bash
curl -X DELETE https://synapse-api.pyrx.tech/v1/workspace/domains/c3d4e5f6-7890-1234-abcd-ef1234567890 \
-H "Authorization: Bearer <jwt>"

Auth: JWT (dashboard). Requires domains:write permission.

Response

Returns 204 No Content on success.

Error: Domain Not Found (404)

json
{
"detail": "Domain not found"
}

DNS Provider Detection

When a domain is accessed via the detail endpoint, Synapse automatically detects the DNS provider by querying NS records. The detected provider is returned in the dns_provider field and cached on the domain record.

Supported Providers

Provider IDDisplay Name
cloudflareCloudflare
namecheapNamecheap
godaddyGoDaddy
route53AWS Route 53
googleGoogle Cloud DNS
digitaloceanDigitalOcean
ns1NS1
hetznerHetzner
vultrVultr
linodeLinode (Akamai)
hoverHover
dnsimpleDNSimple
dynDyn (Oracle)
vercelVercel
wordpressWordPress.com
otherUnrecognized provider