10xDotIn Developer Docs

Campaign Email Automation Through 10xDotIn

Configure sender profiles, templates, and campaign email rules using JWT-authenticated 10x handle APIs.

Campaign Email Automation Through 10xDotIn

This guide is for an external developer integrating with 10xDotIn email automation for a handle. It covers the supported API path for setting up verified senders, reusable templates, direct email sends, and campaign email rules such as lead-capture follow-ups or conversion-triggered messages.

Quick Answer: Should This Work With JWT?

Yes, this should work with JWT when all of the following are true:

  • The token is a valid 10xDotIn/Product Suite JWT accepted by the /v2/handles/* API gateway authorizer.
  • The JWT subject maps to a user who has OPERATOR or OWNER access to the target handle.
  • The target handle is active.
  • The account owns the sending domain.
  • The domain email identity is READY.
  • The sender profile is enabled, READY, and has the correct purpose for the action.
  • The email template exists and is active.
  • The transactional email queues are configured in the target environment.

JWT alone is not enough if the user lacks handle access, the sender/domain is not ready, the template does not exist, or the environment queue is unavailable.

If the caller has only a PAT or an OpenAnalyst runtime token, the current email APIs should not be assumed to work. A server-to-server or unattended external automation would need a purpose-built PAT-facing wrapper route or a scoped extension added to 10xDotIn.

Auth Model

Use the same JWT that the signed-in Product Suite user uses for handle-admin APIs.

export TENX_API_BASE="https://ai.10x.in"
export TENX_JWT="<10xdotin-product-suite-jwt>"
export TENX_HANDLE="acme"
export TENX_DOMAIN="example.com"

Pass it on every request:

-H "Authorization: Bearer ${TENX_JWT}"

Required role by route family:

Route familyMinimum handle role
GET /v2/handles/{handle}/email/sendersOPERATOR
PUT /v2/handles/{handle}/email/senders/{senderId}OPERATOR
GET/POST/PUT /v2/handles/{handle}/email/templates*OPERATOR
POST /v2/handles/{handle}/email/messagesOPERATOR
GET /v2/handles/{handle}/email/messages*OPERATOR
GET /v2/handles/{handle}/email/eventsOPERATOR
GET /v2/handles/{handle}/campaigns/{campaignId}/email-rulesCREATOR
POST/PUT/DELETE /v2/handles/{handle}/campaigns/{campaignId}/email-rules*OPERATOR

Supported Endpoint Summary

JobMethod and pathSuccess
Check domain email identityGET /v2/account/domains/{domain}/email-identity200
Reconcile domain email identityPOST /v2/account/domains/{domain}/email-identity/reconcile202
List sender profilesGET /v2/handles/{handle}/email/senders200
Create or update sender profilePUT /v2/handles/{handle}/email/senders/{senderId}200
List templatesGET /v2/handles/{handle}/email/templates200
Create templatePOST /v2/handles/{handle}/email/templates201
Update templatePUT /v2/handles/{handle}/email/templates/{templateId}200
Queue direct email messagePOST /v2/handles/{handle}/email/messages202
List queued/sent messagesGET /v2/handles/{handle}/email/messages200
Get one message and timelineGET /v2/handles/{handle}/email/messages/{messageId}200
List delivery eventsGET /v2/handles/{handle}/email/events200
List campaign email rulesGET /v2/handles/{handle}/campaigns/{campaignId}/email-rules200
Create campaign email rulePOST /v2/handles/{handle}/campaigns/{campaignId}/email-rules201
Update campaign email rulePUT /v2/handles/{handle}/campaigns/{campaignId}/email-rules/{ruleId}200
Delete campaign email ruleDELETE /v2/handles/{handle}/campaigns/{campaignId}/email-rules/{ruleId}204
Get campaign coupon fulfillment configGET /v2/handles/{handle}/campaigns/{campaignId}/coupon-fulfillment200
Enable or update coupon fulfillmentPUT /v2/handles/{handle}/campaigns/{campaignId}/coupon-fulfillment200
Rotate coupon webhook secretPOST /v2/handles/{handle}/campaigns/{campaignId}/coupon-fulfillment/rotate-secret200
Look up coupon fulfillment by emailGET /v2/handles/{handle}/campaigns/{campaignId}/coupon-fulfillments?email={email}200
Retry a failed coupon fulfillmentPOST /v2/handles/{handle}/campaigns/{campaignId}/coupon-fulfillments/{fulfillmentId}/retry?emailHash={emailHash}200

Prerequisite Setup Flow

1. Verify The Domain Email Identity

curl -sS "${TENX_API_BASE}/v2/account/domains/${TENX_DOMAIN}/email-identity" \
  -H "Authorization: Bearer ${TENX_JWT}"

Expected ready shape:

{
  "identity": {
    "identityKey": "us-east-1#example.com",
    "region": "us-east-1",
    "domain": "example.com",
    "status": "READY",
    "requiredDnsRecords": [],
    "mailFromDomain": "bounce.example.com"
  },
  "senderProfiles": []
}

If the status is not READY, reconcile after DNS is configured:

curl -sS -X POST "${TENX_API_BASE}/v2/account/domains/${TENX_DOMAIN}/email-identity/reconcile" \
  -H "Authorization: Bearer ${TENX_JWT}"

Reconcile returns 202; it does not mean DNS is ready immediately. Poll the identity endpoint until status is READY.

2. Create A Sender Profile

Sender profile rules:

  • senderId must start with sender_.
  • localPart must be one of: noreply, notifications, calendar, support, hello.
  • purposes must include the purpose you will use later.
  • Campaign email rules require PRODUCT_NOTIFICATION.
  • Lead-capture OTP verification requires LEAD_VERIFICATION.
  • Direct transactional sends usually use TRANSACTIONAL_API.
curl -sS -X PUT "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/email/senders/sender_notifications" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "example.com",
    "localPart": "notifications",
    "displayName": "Acme Notifications",
    "replyTo": "support@example.com",
    "purposes": ["PRODUCT_NOTIFICATION", "LEAD_VERIFICATION", "TRANSACTIONAL_API"],
    "enabled": true
  }'

Response:

{
  "sender": {
    "senderId": "sender_notifications",
    "domain": "example.com",
    "localPart": "notifications",
    "fromEmail": "notifications@example.com",
    "displayName": "Acme Notifications",
    "replyTo": "support@example.com",
    "purposes": ["PRODUCT_NOTIFICATION", "LEAD_VERIFICATION", "TRANSACTIONAL_API"],
    "enabled": true,
    "status": "READY",
    "identityKey": "us-east-1#example.com"
  }
}

3. Create A Template

Template rules:

  • templateId must start with tmpl_.
  • A template needs a subject and at least one body field, html or text.
  • Template variables use {{variableName}}.
curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/email/templates" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_lead_followup",
    "name": "Lead follow-up",
    "subject": "Thanks for reaching out, {{firstName}}",
    "html": "<p>Hi {{firstName}}, thanks for your interest in {{service}}.</p>",
    "text": "Hi {{firstName}}, thanks for your interest in {{service}}."
  }'

Response:

{
  "template": {
    "handle": "acme",
    "templateId": "tmpl_lead_followup",
    "name": "Lead follow-up",
    "activeVersion": 1,
    "status": "ACTIVE"
  }
}

Direct Send Flow

Use POST /v2/handles/{handle}/email/messages when the integration wants to queue a single outbound email directly.

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/email/messages" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "sender_notifications",
    "to": ["buyer@example.com"],
    "purpose": "TRANSACTIONAL_API",
    "idempotencyKey": "receipt-ord_12345",
    "consentAttestation": true,
    "templateId": "tmpl_lead_followup",
    "variables": {
      "firstName": "Asha",
      "service": "AI workflow setup"
    }
  }'

Accepted response:

{
  "message": {
    "messageId": "msg_abc123",
    "handle": "acme",
    "status": "QUEUED",
    "purpose": "TRANSACTIONAL_API",
    "senderId": "sender_notifications",
    "recipientCount": 1,
    "fromEmail": "Acme Notifications <notifications@example.com>",
    "createdAt": "2026-06-12T08:00:00.000Z"
  }
}

202 QUEUED means the API stored the message and queued delivery. It is not proof of inbox delivery. Use the message and event endpoints for delivery state.

Campaign Email Rule Flow

Use campaign email rules when 10xDotIn should send emails automatically in response to campaign events.

Supported rule triggers:

TriggerMeaningDelay
LEAD_CAPTUREDSend when a campaign lead is capturedImmediate
LEAD_CAPTURED_DELAYEDSchedule a follow-up after lead captureRequires delayMinutes
CONVERSIONSend when a campaign conversion is recordedImmediate

Delayed sends require delayMinutes from 15 through 43200 minutes, which is 30 days.

Creating a rule does not send emails to existing leads retroactively. It applies to future trigger jobs for that campaign.

Coupon Fulfillment For Verified Leads

Use coupon fulfillment when a verified lead should receive a unique coupon from your system before a coupon email is sent. This is separate from normal lead.captured webhooks: lead capture, owner alerts, regular webhooks, and normal campaign email rules continue after the lead is verified. Only rules with requiresCoupon: true wait for coupon fulfillment.

Requirements:

  • The campaign goal must be LEAD_CAPTURE.
  • Lead verification must be enabled with EMAIL_OTP or EMAIL_REPLY_YES.
  • Coupon fulfillment must be enabled on the campaign.
  • The coupon email rule must set requiresCoupon: true.
  • The coupon email template should include {{couponCode}} and any optional variables your webhook returns.

Enable Coupon Fulfillment

curl -sS -X PUT "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/coupon-fulfillment" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "webhookUrl": "https://customer.example.com/10x/coupon",
    "timeoutMs": 5000,
    "maxAttempts": 3
  }'

The first enable response includes a one-time couponFulfillmentSecret. Store it in your webhook service. Later GET responses only include secretPreview, never the raw secret.

{
  "handle": "acme",
  "campaignId": "cmp_welcome",
  "couponFulfillment": {
    "enabled": true,
    "webhookUrl": "https://customer.example.com/10x/coupon",
    "timeoutMs": 5000,
    "maxAttempts": 3,
    "secretPreview": "cfs_ab...9Q2x",
    "secretVersion": 1
  },
  "couponFulfillmentSecret": "cfs_full_one_time_secret"
}

Rotate the webhook secret when needed:

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/coupon-fulfillment/rotate-secret" \
  -H "Authorization: Bearer ${TENX_JWT}"

Create A Coupon Email Template

Coupon-dependent templates can use all normal lead variables plus:

VariableSource
couponCodeRequired couponCode returned by your webhook
couponExpiresAtOptional ISO timestamp returned by your webhook
Custom variablesSafe keys from variables in your webhook response

Reserved names such as email, leadId, campaignId, name, and couponCode cannot be overridden inside variables.

Create A Coupon-Dependent Rule

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger": "LEAD_CAPTURED",
    "templateId": "tmpl_coupon",
    "senderId": "sender_notifications",
    "requiresCoupon": true,
    "enabled": true
  }'

requiresCoupon: true is rejected with 409 coupon_fulfillment_required until coupon fulfillment is enabled on the campaign. Existing rules without requiresCoupon keep sending normally.

Webhook Request

10xDotIn calls your webhook after a verified lead needs a coupon and no valid cache exists for that campaign/email pair.

{
  "eventType": "campaign.coupon.requested",
  "eventId": "cfr_abc123",
  "handle": "acme",
  "tenantId": "tenant_123",
  "campaignId": "cmp_welcome",
  "leadId": "lead_123",
  "email": "lead@example.com",
  "leadEmailMasked": "le***@example.com",
  "name": "Asha",
  "phone": "+15551234567",
  "fields": {
    "plan": "pro"
  },
  "pageUrl": "https://acme.10x.in",
  "verifiedAt": "2026-06-17T10:00:00.000Z"
}

Headers:

Content-Type: application/json
X-10x-Event-Id: cfr_abc123
X-10x-Timestamp: 2026-06-17T10:00:00.000Z
X-10x-Signature: sha256=<hex>

Verify the signature with HMAC SHA-256 over ${timestamp}.${rawBody}:

import crypto from "node:crypto";

function verify10xCouponSignature({ secret, timestamp, rawBody, signature }) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  const expectedBytes = Buffer.from(expected);
  const signatureBytes = Buffer.from(signature || "");
  return (
    expectedBytes.length === signatureBytes.length &&
    crypto.timingSafeEqual(expectedBytes, signatureBytes)
  );
}

Reject requests with missing headers, invalid signatures, or stale timestamps.

Webhook Response

Return HTTP 2xx with JSON:

{
  "couponCode": "SAVE20",
  "couponExpiresAt": "2026-06-18T12:00:00.000Z",
  "variables": {
    "discountPercent": "20",
    "couponUrl": "https://example.com/apply?code=SAVE20"
  }
}

Response limits:

  • Body must be valid JSON and no larger than 32 KB.
  • couponCode is required and max 128 characters after trimming.
  • couponExpiresAt is optional but must be an ISO timestamp if present.
  • variables is optional, max 25 keys.
  • Variable keys must match /^[A-Za-z][A-Za-z0-9_]{0,63}$/.
  • String variable values are trimmed and max 512 characters.

Cache, Failure, And Retry Behavior

10xDotIn caches one coupon per verified normalized email and campaign for 24 hours. Repeat verified submissions from the same email in that window reuse the same coupon and can resend the coupon email without calling your webhook again.

Webhook timeouts, network errors, non-2xx responses, invalid JSON, invalid coupon responses, and oversized responses are retried. Default attempts are 3, with delayed retries. After terminal failure, coupon-dependent emails are not sent and the fulfillment is marked FAILED.

Look up a lead's coupon fulfillment state:

curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/coupon-fulfillments?email=lead@example.com" \
  -H "Authorization: Bearer ${TENX_JWT}"

Example failed response shape:

{
  "handle": "acme",
  "campaignId": "cmp_welcome",
  "emailMasked": "le***@example.com",
  "fulfillmentId": "cfr_abc123",
  "cache": {
    "status": "MISS",
    "valid": false
  },
  "fulfillment": {
    "status": "FAILED",
    "fulfillmentId": "cfr_abc123",
    "attempts": 3,
    "maxAttempts": 3,
    "lastError": "coupon_webhook_non_2xx"
  }
}

To retry a failed fulfillment, compute:

emailHash = sha256(lowercase(handle) + ":" + lowercase(campaignId) + ":" + lowercase(trim(email)))

Then call:

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/coupon-fulfillments/cfr_abc123/retry?emailHash=${EMAIL_HASH}" \
  -H "Authorization: Bearer ${TENX_JWT}"

If a valid cache already exists, retry releases waiting coupon emails without calling your webhook and returns status: "CACHE_HIT".

Create An Immediate Lead-Captured Rule

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger": "LEAD_CAPTURED",
    "templateId": "tmpl_lead_followup",
    "senderId": "sender_notifications",
    "enabled": true,
    "variableMappings": {
      "firstName": "firstName",
      "service": "fields.service"
    }
  }'

Response:

{
  "rule": {
    "ruleId": "cer_2f3ddf1b-7d15-4f70-83bb-1d28b91a42c5",
    "campaignId": "cmp_welcome",
    "trigger": "LEAD_CAPTURED",
    "delayMinutes": null,
    "templateId": "tmpl_lead_followup",
    "senderId": "sender_notifications",
    "variableMappings": {
      "firstName": "firstName",
      "service": "fields.service"
    },
    "requiresCoupon": false,
    "enabled": true,
    "version": 1,
    "createdAt": "2026-06-12T08:00:00.000Z",
    "updatedAt": "2026-06-12T08:00:00.000Z"
  }
}

Create A Delayed Follow-Up Rule

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger": "LEAD_CAPTURED_DELAYED",
    "delayMinutes": 1440,
    "templateId": "tmpl_lead_followup",
    "senderId": "sender_notifications",
    "enabled": true
  }'

1440 schedules the email approximately one day after the lead-capture trigger.

Create A Conversion Rule

curl -sS -X POST "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger": "CONVERSION",
    "templateId": "tmpl_lead_followup",
    "senderId": "sender_notifications",
    "enabled": true
  }'

List Rules

curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules" \
  -H "Authorization: Bearer ${TENX_JWT}"

Update A Rule

Use expectedVersion when your UI or integration edits a rule to avoid overwriting a concurrent change.

curl -sS -X PUT "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules/cer_2f3ddf1b-7d15-4f70-83bb-1d28b91a42c5" \
  -H "Authorization: Bearer ${TENX_JWT}" \
  -H "Content-Type: application/json" \
  -d '{
    "trigger": "LEAD_CAPTURED_DELAYED",
    "delayMinutes": 2880,
    "templateId": "tmpl_lead_followup",
    "senderId": "sender_notifications",
    "enabled": true,
    "expectedVersion": 1
  }'

If the version has changed, the API returns 409 version_conflict.

Delete A Rule

curl -sS -X DELETE "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/campaigns/cmp_welcome/email-rules/cer_2f3ddf1b-7d15-4f70-83bb-1d28b91a42c5" \
  -H "Authorization: Bearer ${TENX_JWT}"

The delete is a soft delete and returns 204. Repeating the delete is safe.

Template Variables For Campaign Rules

Campaign-triggered sends render variables from the lead snapshot captured at trigger time. Default variables include:

VariableSource
leadIdLead id
emailLead email
nameLead full name
firstNameExplicit first name or first word of name
phoneLead phone
companyLead company
serviceLead service
messageLead message
sourceLead source

Use variableMappings to map template variables to either top-level lead fields or custom fields:

{
  "variableMappings": {
    "requestedService": "fields.service",
    "companyName": "company"
  }
}

Mapping keys and values must be short safe identifiers containing letters, numbers, _, ., or -.

Delivery And Debugging

Campaign email rules create transactional email messages asynchronously when trigger jobs run. The final delivery worker validates the sender and domain again before sending. If a sender or domain becomes disabled after rule creation, the queued message can be denied instead of sent.

Inspect message state:

curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/email/messages?limit=25" \
  -H "Authorization: Bearer ${TENX_JWT}"

Inspect one message timeline:

curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/email/messages/msg_abc123" \
  -H "Authorization: Bearer ${TENX_JWT}"

Inspect events:

curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/email/events?messageId=msg_abc123" \
  -H "Authorization: Bearer ${TENX_JWT}"

When listing events without messageId or recipient, include at least purpose or since.

Common Errors

StatusErrorMeaningFix
401missing_bearer_tokenNo bearer token was suppliedSend Authorization: Bearer <jwt>
401Authorizer failureJWT is expired, malformed, or not accepted by the API gateway authorizerObtain a fresh 10xDotIn/Product Suite JWT
403forbiddenJWT user has no access to the handle or accountGrant the user handle access
403insufficient_roleUser has a lower role than requiredUse an OPERATOR or OWNER user
404account_domain_not_foundDomain is not attached to this accountAttach the domain first
409domain_email_identity_not_readyDomain email identity is not verified and readyFix DNS and reconcile identity
400invalid_sender_idSender id is missing or does not start with sender_Use a valid sender id
400sender_local_part_not_allowedSender local part is not in the allowlistUse noreply, notifications, calendar, support, or hello
404sender_profile_not_foundSender profile does not existCreate the sender profile
409sender_profile_not_ready or sender_not_readySender is disabled or pausedEnable or recreate a ready sender
403sender_purpose_not_allowedDirect send purpose is not allowed for senderAdd the purpose or use another sender
409sender_missing_product_notification_purposeCampaign rule sender lacks PRODUCT_NOTIFICATIONAdd PRODUCT_NOTIFICATION to sender purposes
404campaign_not_foundCampaign id does not exist for this handleCreate or correct the campaign id
404email_template_not_foundTemplate id does not existCreate or correct the template id
409email_template_not_activeTemplate exists but is paused/inactiveActivate or update the template
400invalid_triggerCampaign email trigger is invalidUse LEAD_CAPTURED, LEAD_CAPTURED_DELAYED, or CONVERSION
400delay_minutes_required_for_delayed_triggerDelayed trigger is missing delayProvide delayMinutes
400delay_minutes_below_minimumDelay is shorter than 15 minutesUse LEAD_CAPTURED or set delay to at least 15
400delay_minutes_above_maximumDelay is longer than 30 daysUse a delay no greater than 43200
409version_conflictRule was edited since the caller read itRe-read and retry with latest expectedVersion
400consent_attestation_requiredDirect send did not attest recipient consentSet consentAttestation: true
409email_recipient_suppressedRecipient is suppressed for this tenantDo not retry until suppression is resolved
429email_quota_exceededTenant email quota is exhaustedRetry after quota reset or reduce volume
503transactional_email_queue_unavailableDelivery queue is not configured or unavailableCheck target environment health

Validation Checklist For External Developers

Before enabling automation for a customer:

  1. Confirm GET /v2/account/domains/{domain}/email-identity returns identity.status = "READY".
  2. Confirm GET /v2/handles/{handle}/email/senders returns the selected sender with enabled = true, status = "READY", and the required purpose.
  3. Confirm GET /v2/handles/{handle}/email/templates returns the selected active template.
  4. Queue one direct test email with a unique idempotencyKey.
  5. Create a test campaign email rule on a test campaign.
  6. Trigger a test lead or conversion event.
  7. Confirm a message appears under GET /v2/handles/{handle}/email/messages.
  8. Confirm events show SENT or a specific denial/failure reason.

Security Guidance

  • Do not expose JWTs in browser logs, server logs, analytics payloads, or screenshots.
  • Do not store user JWTs as permanent credentials. Treat them as session credentials and rotate/refresh through the product's normal auth flow.
  • Do not use PATs for current email routes. They are not accepted on this surface.
  • Do not write directly to DynamoDB tables. The APIs perform handle access, sender purpose, identity readiness, suppression, quota, and idempotency checks.
  • For external BFFs, proxy only an allowlist of the routes in this document and preserve upstream status codes and error codes.
  • For unattended server-to-server email automation, request a new 10xDotIn public PAT wrapper design instead of trying to reuse internal JWT-only routes.

For direct one-off email sending examples and message/event inspection, see Email Sending Through 10xDotIn.

Updated Jun 19, 2026