DEVELOPER GUIDE

Your first integration,
without the guesswork.

A small HTTP API for transactional email. Start with a verified domain, then keep the API key on your server.

1. Create your workspace

Create an account, then follow the customer onboarding wizard. New accounts open it automatically. You can resume it from Get started in the dashboard. Add your sending domain and publish its ownership and SPF records, then check verification to generate the DKIM key. Publish the returned DKIM and DMARC records and check again. Keep one SPF and one DMARC record; merge existing settings instead of replacing them. Verify your account email with the eight-digit code in Transactional setup. Keep API keys on your server. Signing provisioning and account sending access must also be ready; the dashboard and validation report show remaining blockers.

Install the server-side SDK directly from Emailer API:

npm install https://emailerapi.com/sdk/amgmail-sdk-0.13.1.tgz
python -m pip install https://emailerapi.com/sdk/amgmail-0.4.1-py3-none-any.whl

These versioned downloads include the developer event APIs below. Package names remain @amgmail/sdk and amgmail; these releases are distributed here and are not published on npm or PyPI.

Your onboarding wizard and launch checklist

The onboarding wizard guides each account through domain and DNS, account email, an approved template, the correct event connection, a domain-scoped sending-only key, and launch review. Completed actions are saved in your account. The browser remembers only your selected domain and email type; secrets are shown once and are never saved there. Resuming checks current server evidence, including revoked or stale setup. Use Back or the step menu to revisit a step. Finishing setup sends no email.

In Transactional setup, select the sending domain and customer event. The checklist shows account access, owner verification, domain ownership, recent signing, the approved published template, the correct verifier and a domain-scoped sending-only key. Templates and connections are shown for the selected domain. Payment receipts and paid orders require Stripe; other supported events use your application callback.

Configuration, reporting coverage and first-delivery evidence are separate. A connected verifier still needs a real event; API acceptance and relay acceptance do not prove destination delivery. Connected Gmail reporting can have insufficient data, and Yahoo enrollment does not prove complaint receipt. Refresh after changing DNS, keys or provider setup.

Read the same checklist with a dashboard session or full-access key: GET /v1/transactional/status?domain_id=YOUR_DOMAIN_ID&event=account.verification. This creates no email, event authorization or quota reservation and makes no provider request. It is setup evidence; always validate the exact message before sending. Suppression, event freshness, account quota, shared capacity and current service checks still apply.

Transactional-only safeguards

Production sends require a reviewed template version and a verified, fresh customer event. Each event binds one recipient to the exact sender and rendered content, expires within one hour, and can authorize only one queued message. A contact record, arbitrary transaction label or customer-published template alone cannot authorize sending.

The fixed catalog supports verification codes, password resets, sign-in alerts, order confirmations, payment receipts and appointment confirmations. Variables accept only constrained codes, identifiers, dates and HTTPS links on the verified domain. Sender, subject and body overrides, Cc/Bcc, attachments and custom headers are blocked. Broadcasts and marketing content are unavailable. Required transactional mail does not depend on marketing subscription preferences; bounce and complaint suppressions still apply.

Template approval, event freshness, revocation, suppression and domain state are checked at admission and again immediately before SMTP. A revoked integration invalidates its event authorizations. An already submitted email cannot be recalled. These controls limit abuse but cannot guarantee that a dishonest application owner reports real activity; the callback authenticates that application’s assertion, not independent payment-provider evidence. Payment receipts and paid-order confirmations now require direct Stripe verification; use the Stripe guide below.

2. Choose a fixed template

In Transactional setup, choose a verified domain and an event type. The catalog installs a published, approved template with restricted variables. Reinstalling reuses that template while its approved version is still published. If you publish an edited version, reinstalling creates a fresh approved catalog template and preserves your edited original. You can also use a full-access key or dashboard session:

POST /v1/transactional/templates
{"domain_id":"YOUR_DOMAIN_ID","kind":"account.verification"}

The response returns id, version_id, event and the required variable rules. Repeating the same installation returns its existing template. Custom and AI-generated drafts remain editable through the template APIs; publishing a draft does not authorize it for sending. Editing or publishing a new version requires a new approval.

Discover and manage transactional email

Build setup screens, inspect event authorizations and disconnect integrations from your own application. All endpoints use https://emailerapi.com. Keep API keys on your server.

OperationPurpose and access
GET /v1/transactional/catalogPublic catalog of supported events, template placeholders and variable types. No authentication.
GET /v1/transactional/providersList provider connections. Full-access API key or dashboard session.
GET /v1/transactional/integrationsList application callbacks. Full-access API key or dashboard session.
GET /v1/transactional/eventsList authorizations. Full-access or sending-only API key.
GET /v1/transactional/events/{id}Inspect one authorization with an API key.
DELETE /v1/transactional/events/{id}Revoke an active authorization with an API key.

Domain-scoped keys can read and revoke only events tied to their domain. Reads never return connection credentials, callback secrets or proof digests. Use existing provider/integration DELETE endpoints to disconnect a connection.

Browse every page

All three lists accept limit from 1 to 100 (default 50), and return object, data and has_more. Results are newest first. For the next page, set after to the last item ID; to go back, set before to the first item ID. Supply only one cursor. An invalid or inaccessible cursor returns 400.

curl https://emailerapi.com/v1/transactional/catalog
curl 'https://emailerapi.com/v1/transactional/events?limit=50' \
  -H "Authorization: Bearer $EMAILER_API_KEY"

Node

import { AMGMail } from "@amgmail/sdk";
const mail = new AMGMail(process.env.EMAILER_API_KEY);
let after;
do {
  const result = await mail.transactional.events.list({ limit: 50, ...(after ? { after } : {}) });
  if (result.error) throw new Error(result.error.code);
  const page = result.data;
  for (const event of page.data) console.log(event.id, event.status);
  after = page.has_more ? page.data.at(-1).id : undefined;
} while (after);

Python

import os
from amgmail import AMGMail
mail = AMGMail(os.environ["EMAILER_API_KEY"])
after = None
while True:
    result = mail.transactional.events.list(limit=50, **({"after": after} if after else {}))
    if not result.ok:
        raise RuntimeError(result.error.code)
    page = result.data
    for event in page["data"]:
        print(event["id"], event["status"])
    if not page["has_more"]:
        break
    after = page["data"][-1]["id"]

Use transactional.catalog(), transactional.providers.list() and transactional.integrations.list() in either SDK. The two connection lists accept the same pagination options.

Inspect or revoke an authorization

Event status is active, expired, consumed or revoked. Read using transactional.events.get(id) and revoke using transactional.events.revoke(id). Revoking an active event returns revoked: true; repeating it is safe. Expired or consumed events remain unchanged and return revoked: false. Revocation does not cancel an email already queued.

# Set EVENT_ID to an authorization you intend to revoke.
curl -X DELETE "https://emailerapi.com/v1/transactional/events/$EVENT_ID" \
  -H "Authorization: Bearer $EMAILER_API_KEY"

Missing or invalid credentials return 401. Insufficient management scope returns 403. An unknown or inaccessible event returns 404; malformed IDs and pagination parameters return 400. Read/list responses omit evidence; event creation can return application_attested or stripe_verified.

These APIs manage the existing approved-template and verified-event workflow. See the complete OpenAPI contract for request and response fields.

3. Connect live application events

Register an HTTPS callback on the exact verified domain with POST /v1/transactional/integrations. Supply domain_id and callback_url. Store the returned shared_secret in your server’s secret manager; it is returned only once. At most five active integrations are allowed.

For each event verification, Emailer API POSTs a JSON request and an X-AMGMail-Proof-Signature header containing HMAC-SHA256 of the exact request bytes. The request includes event_id, event_type, recipient, template_id, version_id, payload_sha256 and a random nonce.

Verify the signature before parsing or trusting the request. Look up the event in your own database and check the exact customer, recipient, event type and message context. Reject unknown, inactive, mismatched or stale events. The callback must never automatically approve every request. This Node example shows the signature protocol; replace loadMatchingActiveCustomerEvent with your real database check:

import { createHmac, timingSafeEqual } from 'node:crypto';
const mac = text => createHmac('sha256', process.env.AMG_EVENT_SECRET)
  .update(text).digest('hex');

// rawBody is the exact UTF-8 HTTP request body; cap it at 16 KiB.
async function verifyEvent(rawBody, suppliedSignature) {
  if (!/^[a-f0-9]{64}$/.test(suppliedSignature || '') ||
      !timingSafeEqual(Buffer.from(mac(rawBody), 'hex'),
                       Buffer.from(suppliedSignature, 'hex'))) return null;
  const request = JSON.parse(rawBody);
  const event = await loadMatchingActiveCustomerEvent(request);
  if (!event) return null; // Return HTTP 403. Never sign unverified input.
  const occurred_at = event.occurredAt.toISOString();
  const signed = JSON.stringify({ ...request, occurred_at, customer_active: true });
  return { occurred_at, customer_active: true, signature: mac(signed) };
}

Return the object as JSON with HTTP 200. The event must have occurred in the previous 15 minutes; at most one minute of future clock skew is tolerated. Requests time out after 10 seconds and responses are limited to 16 KiB. Redirects, private-network destinations, custom ports and credential-bearing URLs are rejected. The response signature binds the nonce and all original request fields, preventing reuse for another request.

4. Verify an event and send

Use a sending-only key, preferably restricted to your domain. The event endpoint checks your callback before issuing an authorization. Replace all example variables below with your application’s actual records and secrets.

import { AMGMail } from '@amgmail/sdk';
const mail = new AMGMail(process.env.AMG_MAIL_API_KEY, { baseUrl: "https://emailerapi.com/v1" });
const email = {
  to: customer.email,
  template: { id: process.env.AMG_TEMPLATE_ID, variables: { CODE: verificationCode } }
};
const verified = await mail.transactional.events.create({
  integration_id: process.env.AMG_INTEGRATION_ID,
  event_id: signupEvent.id, // Stable ID from your database, not a new retry ID.
  event: 'account.verification', email
});
if (verified.error) throw new Error(verified.error.message);
const payload = { ...email, metadata: {
  event: verified.data.event, transaction_id: verified.data.id
}};
const checked = await mail.emails.validate(payload);
if (checked.error) throw new Error(checked.error.message);
if (!checked.data.can_enqueue || !checked.data.delivery.configuration_ready)
  throw new Error('Resolve the validation blockers before sending.');
const result = await mail.emails.send(payload, { idempotencyKey: signupEvent.id });
if (result.error) throw new Error(result.error.message);
// result.data.id identifies a queued message; it does not prove delivery.

Python uses the same payloads: mail.transactional.events.create(...), mail.emails.validate(payload), then mail.emails.send(payload, idempotency_key=signup_event_id). Inspect result.ok, result.data and result.error. Direct HTTP uses POST /v1/transactional/events, POST /v1/emails/validate and POST /v1/emails.

Validate without sending

POST /v1/emails/validate checks a new send without reserving send quota or storage, consuming its event, or contacting SMTP. Pass the same approved payload as sending and omit Idempotency-Key. HTTP 200 returns a report: can_enqueue indicates current admission eligibility, while delivery.configuration_ready reports configured infrastructure and signing readiness.

Inspect the named checks for exact blockers, including approved_template_required, template_not_approved, event_not_verified, event_expired and recipient_suppressed. Named checks include owner verification, current signing, application proof, shared queue capacity and whether pacing fits inside the event’s expiry. The report is a snapshot; it does not reserve capacity, check recipient mailbox existence, predict inbox placement, or guarantee future delivery timing. All checks run again when sending. Authentication and metadata-only request logs may be recorded.

Retry without duplicate mail

Persist the source event ID, returned authorization ID and send idempotency key. Retrying event verification with the same source ID and identical content returns its existing authorization while valid; changed content returns 409. Retrying email admission with the same key and payload returns the original accepted message during the 24-hour replay window. Never replace a retry key after uncertain acceptance. Neither SDK automatically retries mutations or follows redirects.

One authorization cannot produce multiple messages, even with different keys or concurrent requests. A batch is atomic and requires a distinct valid event for every message. Schedules must fit inside event and account approval expiry. Canceling a queued message does not refund quota or make its event reusable.

Observe delivery and failures

Read GET /v1/emails/{id} and GET /v1/emails with full-access authentication, or open Email Logs. API acceptance, SMTP acceptance and remote-MX delivery are separate events. A successful MX handoff does not prove inbox placement. Recipient-invalid bounces suppress the address; policy blocks pause the sending pool. Delayed negative DSNs are matched through signed, expiring return addresses and exact dispatch records. A recipient who has that return address can submit a negative report; it is not independent provider attestation. Positive DSN reports do not establish delivery. The complaint receiver authenticates Yahoo’s dedicated DKIM signatures and matches immutable dispatch IDs before applying suppression. Yahoo requires separate domain enrollment before it will send real reports; enrollment is not yet confirmed. Other provider feeds are not yet enrolled. Complaint counts cover received reports only. Unknown measurements remain unavailable.

GET /v1/usage reports recipient reservations, UTC quota windows and retained logical storage. Sending capacity and IP warmup pacing can be lower than the account allowance. Canceled and failed accepted messages still consume quota. Low storage blocks new admission without a charge. The OpenAPI contract documents exact fields and failure codes.

Delivery webhooks

Create and manage endpoints in the dashboard or through /v1/webhooks. Store the returned signing secret securely. Authenticate delivery callbacks against the exact raw request body and deduplicate their delivery IDs. See the Webhook schemas and authentication protocol for the signature format, supported events and bounded retry behavior. Event and attempt history is available through /v1/webhooks/{id}/events; response bodies are redacted.

Account activation

Create your account, verify your email and sending domain, install a fixed transactional template, and connect your application’s event callback. A successful event proof completes the integration. The dashboard shows account eligibility separately from current service capacity.

Free growth roadmap: up to 50,000/day is planned and unavailable today. Strict warm-up, pristine sending evidence, human review and provisioned capacity are required. Read the growth policy; The growth object in GET /v1/usage distinguishes the target from active limits.

New accounts start at 100 recipient reservations per UTC day and 3,000 per calendar month. New sending domains start at 100 per day and hour. Existing saved limits are preserved. The initial shared IP supports 1,000 attempts per UTC day with at least three seconds between attempts. The last 50 daily slots are reserved for platform verification emails. Shared capacity can be lower than the sum of account quotas. A capacity rejection consumes no quota. Limits remain conservative until real delivery history supports an increase; there are no automatic overage charges.

Sending is paused automatically when node health or feedback is unavailable. The API checks current node readiness and domain/IP capacity before accepting mail and rechecks eligibility before SMTP. The health endpoint reports service availability, not individual account approval or inbox placement. The dedicated OVH transport passed an external SPF, DKIM and DMARC test on September 7, 2026; the self-service owner-code, application-proof, SDK delivery and delayed-bounce paths were also tested using an owned domain and mailbox.

Moving from Resend

Emailer API is powered by AMG Mail. The @amgmail/sdk and amgmail packages remain supported; configure their base URL to https://emailerapi.com/v1 as shown below. Existing accounts and API keys work on the new domain.

Emailer API provides a transactional email API, Node and Python SDK downloads, validation without sending, template/event authorization, logs, quota/storage snapshots and signed delivery callbacks. It is not a drop-in replacement for all Resend products. Marketing and broadcasts are intentionally disabled. Open/click observations, an analytics dashboard and independent Stripe verification are available. Inbound customer mail and general automation tools remain outside this release. Install the Node and Python SDKs using the versioned direct downloads above. Use the published contract rather than assuming endpoint or webhook compatibility.

Verify Stripe payments independently

In Transactional setup, connect a restricted live Stripe key with read permissions for Events, Charges and Checkout Sessions. The key is encrypted and never returned. Emailer API makes read requests only. Payment receipts require charge.succeeded, a captured positive-value unrefunded charge, and the exact provider-record email. Set PAYMENT to the ch_ ID. Events must be at most 15 minutes old.

Install the payment receipt template and a domain-scoped sending API key. Call this helper from your existing signature-verified Stripe webhook. Keep the AMG API key in your server’s secret manager.

Node

import { AMGMail } from "@amgmail/sdk";
const mail = new AMGMail(process.env.AMG_MAIL_API_KEY, { baseUrl: "https://emailerapi.com/v1" });

/** Call from a signature-verified Stripe webhook in your server application. */
export async function sendStripeReceipt(mail, { connectionId, templateId, stripeEventId, chargeId, recipient, receiptUrl }) {
  const email = { to: recipient, template: { id: templateId, variables: { PAYMENT: chargeId, URL: receiptUrl } } };
  const proof = await mail.transactional.events.create({ provider_connection_id: connectionId,
    event_id: stripeEventId, event: 'payment.receipt', email });
  if (proof.error) throw new Error(proof.error.code);
  const payload = { ...email, metadata: { transaction_id: proof.data.id, event: proof.data.event } };
  const validation = await mail.emails.validate(payload);
  if (validation.error) throw new Error(validation.error.code);
  if (!validation.data.can_enqueue) throw new Error('transactional_email_not_ready');
  const result = await mail.emails.send(payload, { idempotencyKey: `stripe:${stripeEventId}:receipt` });
  if (result.error) throw new Error(result.error.code);
  return result.data; // Queue acceptance; inspect delivery webhooks for the outcome.
}

Python

import os
from amgmail import AMGMail
mail = AMGMail(os.environ["AMG_MAIL_API_KEY"], base_url="https://emailerapi.com/v1")

"""Call from a signature-verified Stripe webhook in your server application."""
def send_stripe_receipt(mail, *, connection_id, template_id, stripe_event_id, charge_id, recipient, receipt_url):
    email = {"to": recipient, "template": {"id": template_id, "variables": {"PAYMENT": charge_id, "URL": receipt_url}}}
    proof = mail.transactional.events.create(provider_connection_id=connection_id, event_id=stripe_event_id,
                                             event="payment.receipt", email=email)
    if not proof.ok:
        raise RuntimeError(proof.error.code)
    payload = {**email, "metadata": {"transaction_id": proof.data["id"], "event": proof.data["event"]}}
    validation = mail.emails.validate(payload)
    if not validation.ok:
        raise RuntimeError(validation.error.code)
    if not validation.data["can_enqueue"]:
        raise RuntimeError("transactional_email_not_ready")
    result = mail.emails.send(payload, idempotency_key="stripe:" + stripe_event_id + ":receipt")
    if not result.ok:
        raise RuntimeError(result.error.code)
    return result.data  # Queue acceptance, not delivery confirmation.

For order.confirmed, use a live paid Checkout Session event and put its cs_ ID in ORDER. Free, incomplete and test-mode transactions are rejected. Disconnecting a provider revokes its authorizations. Application callbacks remain available for account, security and appointment events.

Delivery and engagement analytics

Open Analytics for domain filters, daily charts, CSV export, delivery outcomes, unique and total opens/clicks, permanent/transient/unclassified bounces, spam complaints, rates and tracking coverage. The same statistics are available through mail.emails.metrics(). Subscribe to email.opened and email.clicked webhooks for the first observation per recipient and event.

Tracking is enabled by default for eligible order, receipt and appointment templates. It is never added to account verification, password resets or security alerts. Links with query strings, fragments or a different hostname remain unchanged. Use GET/PATCH /v1/analytics/settings or mail.analytics.settings to control future messages. Links expire after 30 days; observations are deduplicated per link per minute and bounded to 1,000 per link.

Open and click observations are not proof of a human reading. Privacy proxies and scanners can trigger requests; unclassified does not mean human. Rates use the denominators documented in the API response. No spam-folder placement is measured, and no complaint report does not prove that nobody complained. Historical untracked mail has null engagement metrics.

Bodies and attachments expire after 30 days for completed messages; pending and uncertain deliveries are preserved. Detailed engagement events last 90 days, while aggregate counts, delivery identities, suppressions and idempotency records remain. Storage and delivery checks fail closed. During launch, any spam complaint or a bounce rate of at least 5% after 100 relay acceptances in 24 hours holds the affected account for operator review. Alerts run independently on the mail node; notification delivery requires an operator-configured destination.

Customer spam monitoring and complaint coverage

Open Transactional setup after verifying a domain, then check Analytics for provider coverage and dated measurements. Each customer's domain, template groups, reports and sending holds are isolated. New verified domains enter the reporting setup queue automatically.

Yahoo: enroll every signing domain

Emailer API operations enrolls each exact DKIM signing domain in Yahoo Sender Hub using the managed complaint mailbox. If Yahoo requires a DNS TXT record, setup displays the exact record. Only an authorized Emailer API operator can confirm enrollment after checking the provider. Enrollment checks become due for review after 30 days. Enrollment is separate from receiving a real complaint.

Authenticated Yahoo feedback is matched to the original message and customer. A received spam complaint suppresses that recipient for that customer and holds that customer's sending for review. Analytics counts actual reports received in the last 90 days. No reports received does not prove that nobody complained.

Gmail: connect Google Postmaster Tools

Emailer API registers your verified sending domain for managed reporting and supplies a Google DNS verification TXT record. Add the record and select Check Gmail. If you already manage the domain in Google Postmaster Tools, you may grant the reporting account shown in setup read access instead. This connection reads domain reports and never accesses a Gmail mailbox.

Google's current Postmaster v2 API supplies aggregate spam rates, Emailer API customer/domain/template feedback groups, SPF/DKIM/DMARC authentication success, delivery rejection and temporary-failure rates, and exact-domain compliance details when available. It does not expose the former domain/IP reputation rating categories. Emailer API adds a stable, opaque Feedback-ID covered by DKIM; API clients cannot override it. A domain's aggregate rate may include mail sent through other services; Emailer API feedback groups are filtered to this customer.

Reports refresh approximately every six hours. The latest seven days are refreshed and daily history is retained for 90 days, with a CSV export in Analytics. Google delays or withholds measurements when volume is too low. Missing values remain unavailable; an explicit reported zero remains zero. Samples over four days old or checks over 36 hours old are stale. Gmail does not identify individual spam reporters and these reports do not measure inbox or spam-folder placement.

Warnings, holds and review

A fresh reported Gmail spam rate or Emailer API group rate of at least 0.1% raises an operational warning; at least 0.3% holds that customer's sending. Delivery-error rates of at least 5% also warn. Existing complaint and bounce safeguards still apply. Reporting access failures, disconnected reporting, pending Yahoo enrollment, warnings and sending holds feed the independent operational alert service. Low-volume data absence is shown clearly and is not a false all-clear or an automatic spam hold.

Operators review the customer, transaction source and affected template before releasing a hold and must record review evidence. Customers cannot release holds or certify their own Yahoo enrollment. The same old Gmail sample does not immediately reverse a reviewed release. Fresh adverse reports can trigger another hold. Verified live-event and transactional-template checks continue before every send.

Reporting API

Use a dashboard session or full-access key. Sending-only keys cannot access reporting or operations. GET /v1/reputation returns your coverage, dated history and current hold; optional domain_id restricts it to one owned domain. POST /v1/reputation/domains/{id}/gmail or /yahoo accepts {"action":"connect"}, check, or disconnect. Setup mutations share a 60-per-minute account limit. Operator APIs require an independently configured verified-owner allowlist.

Provider references: Google feedback identifiers, Google Postmaster v2 metrics, Yahoo complaint feedback loop.

Built-in setup assistant and optional external agents

The onboarding wizard starts with the kind of customer email you want to send. Sign in with an email login link; Google sign-in appears when configured. You can add a team name later in Connections. Existing verified steps are reused when you add another sender.

Select Help me set this up to use the included Emailer API setup assistant. It can save an email type and framework, add a customer-specified domain, check public DNS, install an approved template and prepare integration files. It reads your actual account progress. It cannot read stored credentials, run arbitrary code, publish DNS or send email. Keep credentials in the secure fields.

For non-payment events, select the domain where your application serves HTTPS: the verification callback must use that exact verified sending domain. Next.js, Node.js, Express and Python starter files are generated from your saved setup. Implement the real customer-event lookup and deploy the callback before sending. Starter examples deliberately refuse to verify fabricated events. Stripe is required for payment receipts and paid-order confirmations.

Review DNS additions

Cloudflare is an optional DNS connection. Enter a token scoped to Zone Read and DNS Edit for your own zone in the secure field. Preview the exact missing TXT records and authorize the additions inside Emailer API. Existing SPF, DMARC and other conflicting records are preserved for manual review; nothing is deleted or overwritten. Plans expire after ten minutes and are checked again before applying. Run a fresh DNS check after publication. Other DNS providers use the same displayed records with manual setup.

Connect ChatGPT or Claude

Open Connections and copy https://emailerapi.com/mcp into your assistant’s custom MCP connection settings. Both use the same OAuth-linked tools and saved progress. Each customer signs in to Emailer API and reviews the named workspace and permissions. Custom connector availability depends on the assistant’s plan and workspace policy; external accounts are optional.

The MCP server supports Streamable HTTP JSON responses, OAuth authorization code with PKCE S256, registered ChatGPT/Claude callbacks, resource-bound access tokens and rotating refresh tokens. Discovery is available at protected resource metadata and authorization server metadata. Scopes are onboarding:read and onboarding:write. Revoke a grant at any time in Connections. DNS application and credential fields require a customer session on the site.

Tools: get_onboarding_state, select_email_type, add_sending_domain, select_sending_domain, check_domain_dns, install_approved_template, prepare_dns_changes, and get_integration_code. Finishing configuration does not send a message. A real event, review of the exact recipient and content, and the normal sending safeguards still apply.