message.comDevelopers

Integrations Live

This is not a general third-party-connections resource. It is the OAuth controller behind the custom-domain setup wizard: connect a DNS provider so message.com can apply the sending-domain records (MX, SPF, DKIM) for you instead of you copying them into your registrar by hand. Four providers: cloudflare, vercel, digitalocean, gcp.

Business integrations like Shopify and WordPress are NOT under this resource. They connect through their own dedicated flows: the Shopify app and the WordPress plugin. There is no Stripe, HubSpot, or Salesforce connection here either; see the sync tutorials for those.

List connected DNS providers

GET/api/v1/integrationsAuth: Bearer

Returns the workspace's active (non-revoked) provider connections. No filters.

Code samples

cURL
curl 'https://app.message.com/api/v1/integrations' \
  -H 'Authorization: Bearer YOUR_WORKSPACE_JWT'
JavaScript
const res = await fetch('https://app.message.com/api/v1/integrations', {
  headers: { Authorization: 'Bearer ' + token }
});
const { integrations } = await res.json();
Python
import requests
r = requests.get(
    "https://app.message.com/api/v1/integrations",
    headers={"Authorization": f"Bearer {token}"},
)
integrations = r.json()["integrations"]
Ruby
require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/integrations")
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
integrations = JSON.parse(res.body)["integrations"]
PHP
<?php
$ctx = stream_context_create([
  "http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$integrations = json_decode(file_get_contents("https://app.message.com/api/v1/integrations", false, $ctx), true)["integrations"];
200 OK · integration
{
  "integrations": [
    {
      "provider": "cloudflare",
      "providerAccountId": "cf-account-id",
      "connectedAt": "2026-05-13T15:30:00Z",
      "metadata": null
    }
  ]
}

Supported providers

ProviderNotes
cloudflareAccount-level OAuth (same endpoints Wrangler uses).
vercelLights up once its marketplace listing is approved.
digitaloceanSelf-serve.
gcpSelf-serve. Requires an extra step to pick a Cloud DNS project after OAuth.

Start a connection

GET/api/v1/integrations/:provider/startAuth: Bearer

Browser-navigate the admin here (not a fetch call: this redirects to the provider's OAuth authorize page). 503 oauth_not_configured if that provider's credentials aren't configured server-side yet.

GET/api/v1/integrations/:provider/callbackAuth: Bearer

The provider redirects here after approval. Public (no auth header: the provider calls it directly), verified via a signed OAuth state parameter. On success or failure it redirects the browser back into the dashboard's domain-setup wizard.

GCP: pick a Cloud DNS project

GET/api/v1/integrations/gcp/projectsAuth: Bearer
POST/api/v1/integrations/gcp/projectAuth: Bearer

GCP-only extra step: after OAuth, list the projects the grant can see, then POST the chosen projectId onto the integration before applying records.

Apply DNS records

POST/api/v1/integrations/:provider/apply-recordsAuth: Bearer

Pushes the workspace's email domain's (or a specific sending domain's) DNS records into the connected provider's zone. SPF is merged into any existing TXT record rather than overwritten; an existing DMARC record is left alone.

FieldTypeDescription
domainrequiredstringThe apex domain whose records to apply.
sendingDomainIdoptionaluuidApply a specific sending domain's records instead of the workspace's single legacy email domain.
Body
{ "domain": "acme.com" }
200 OK
{
  "records": [
    { "type": "MX", "name": "@", "purpose": "inbound routing", "success": true },
    { "type": "TXT", "name": "@", "purpose": "spf", "success": true, "merged": true },
    { "type": "CNAME", "name": "resend._domainkey", "purpose": "dkim", "success": true }
  ],
  "allOk": true
}

Disconnect

DELETE/api/v1/integrations/:providerAuth: Bearer

Revokes the connection (soft: stamps revokedAt, doesn't remove a row). Does not remove DNS records already applied at the provider; those keep working.

Errors

CodeWhen
400 invalid_providerProvider param failed validation.
404 unknown_providerProvider isn't one of the four supported.
404 integration_not_foundNo active connection for that provider on this workspace.
400 no_email_domainApply-records called with no email domain registered yet.
503 oauth_not_configuredThat provider's OAuth client credentials aren't set server-side.
503 resend_not_configured / 502 resend_errorApply-records couldn't read the domain's records from the email provider.

Common pitfalls

  • Looking for Shopify/Stripe/HubSpot/Salesforce here. Wrong resource. Those are separate integrations (plugin, app, or CRM-sync tutorial), not OAuth providers under this path.
  • Calling /start with fetch. It's a redirect flow, not a JSON API call. Navigate the browser to it.
  • Applying records before registering an email domain. apply-records needs a domain (or sendingDomainId) to pull records from first.