message.comDevelopers

Email domain Live

Register the one domain a workspace owns (such as acme.com) and verify the DNS records that let message.com send outbound replies as you and receive inbound tickets at your custom local-parts. This is a singular resource: one domain per workspace, not a collection.

There is no list, no delete, and no manual re-verify action. A background poller re-checks DNS automatically for up to 7 days after registration; re-registering resets that clock.

Get the domain

GET/api/v1/email/domainAuth: Bearer

Returns { domain: null } if the workspace has not registered one yet, otherwise the domain with live DNS record status.

Code samples

cURL
curl 'https://app.message.com/api/v1/email/domain' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/email/domain', {
  headers: { Authorization: 'Bearer ' + token }
});
const { domain } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/email/domain",
    headers={"Authorization": f"Bearer {token}"},
)
domain = r.json()["domain"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/email/domain")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  req = Net::HTTP::Get.new(uri)
  req["Authorization"] = "Bearer #{token}"
  http.request(req)
end
domain = JSON.parse(res.body)["domain"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$domain = json_decode(file_get_contents("https://app.message.com/api/v1/email/domain", false, $ctx), true)["domain"];
200 OK
{
  "domain": {
    "id": "resend-domain-id",
    "name": "acme.com",
    "status": "verified",
    "records": [
      { "type": "MX", "name": "@", "value": "feedback-smtp.message.com", "priority": 10, "status": "verified" },
      { "type": "TXT", "name": "@", "value": "v=spf1 include:amazonses.com ~all", "status": "verified" },
      { "type": "CNAME", "name": "resend._domainkey", "value": "resend._domainkey.message.com", "status": "verified" }
    ]
  }
}

Register a domain

POST/api/v1/email/domainAuth: Bearer

Registers a domain and returns the DNS records you must add at your registrar. Domain status begins as pending and flips to verified once the poller confirms all records. Calling this again re-registers and resets the polling window.

FieldTypeDescription
domainrequiredstringThe apex domain, 3 to 253 characters.
Body
{ "domain": "acme.com" }
200 OK
{
  "domain": {
    "id": "resend-domain-id",
    "name": "acme.com",
    "status": "verified",
    "records": [
      { "type": "MX", "name": "@", "value": "feedback-smtp.message.com", "priority": 10, "status": "verified" },
      { "type": "TXT", "name": "@", "value": "v=spf1 include:amazonses.com ~all", "status": "verified" },
      { "type": "CNAME", "name": "resend._domainkey", "value": "resend._domainkey.message.com", "status": "verified" }
    ]
  }
}

Get by ID

GET/api/v1/email/domain/:idAuth: Bearer

Same response as the plain GET above, scoped by the domain's own ID (the ID this workspace already registered; you cannot look up another workspace's domain by guessing an ID).

DNS records

The records array on the domain object is passed through from our email-delivery provider (currently Resend). Each entry has type, name, value, an optional priority (MX), and a per-record status. Typically an MX record (inbound routing), a TXT record (SPF, authorizing outbound sending), and a CNAME (DKIM signing). Adding a DMARC record at your registrar is optional but recommended; see the DMARC RFC.

Most failures here are propagation delays. Allow up to 24 hours after editing DNS before assuming a record is wrong.

Errors

CodeWhen
400 invalid_bodyDomain string failed validation (3 to 253 characters).
403 admin_requiredAgent role is not admin.
404 not_foundGET by ID: the ID doesn't match this workspace's registered domain.
502 resend_errorThe upstream domain-verification provider returned an error.
503 resend_not_configuredThe domain-verification provider isn't configured server-side.

Common pitfalls

  • Looking for a delete or list endpoint. Neither exists. This is a singular per-workspace resource; re-register to change the domain.
  • Calling a manual re-verify endpoint. There isn't one. The background poller re-checks automatically; re-registering (POST again) resets its 7-day window if you need a fresh cycle.
  • Forgetting DKIM. Without a verified DKIM CNAME, expect Gmail and Microsoft 365 to spam-folder your outbound replies.