intouchvas Developers

Getting Started

The Bulk Email API lets you send transactional email, launch bulk campaigns to recipient groups, and receive delivery-status webhooks — all from your own systems, without the console UI.

Typical workflow
  1. Sign in to the Bulk Email console and open Developer API in the sidebar.
  2. Click Generate key to issue your account's shared API key.
  3. Send it as the x-api-key header on every request below.

Authentication

Your API key is the same credential your SMS and WhatsApp Business integrations already use — one key per intouchvas account, issued and held by identity-service, not something separate per product.

x-api-key: <your key>

Set up a sending domain

By default every send goes out from a shared intouchvas address. To send as you@yourdomain.com instead, register and verify your own domain first — the API rejects any fromEmail/from_email whose domain isn't verified on your account.

POST /sender-domains
curl -X POST https://bulkemail-service.intouchvas.io/api/v1/sender-domains \
  -H "x-api-key: <your key>" \
  -H "Content-Type: application/json" \
  -d '{"domain": "yourdomain.com"}'

Response — 201

{
  "id": 2,
  "domain": "yourdomain.com",
  "status": "pending",
  "dkim_tokens": ["n5m2d7yzzjpf4zvbok6weyiq5gsfj767", "lzpsjh2ar5m4nedwj2pp5lgs63zkzqdq", "vq45eygudpsztyzgli2hgj5n5angsyx2"],
  "dkim_records": [
    {
      "type": "CNAME",
      "name": "n5m2d7yzzjpf4zvbok6weyiq5gsfj767._domainkey.yourdomain.com",
      "value": "n5m2d7yzzjpf4zvbok6weyiq5gsfj767.dkim.amazonses.com"
    },
    { "type": "CNAME", "name": "...", "value": "..." },
    { "type": "CNAME", "name": "...", "value": "..." }
  ],
  "created": "2026-10-15T12:01:52Z"
}

Add the DNS records

Add all three dkim_records entries to your domain's DNS as CNAME records — name is the record name, value is what it points to. This proves domain ownership and lets us sign outgoing mail with a valid DKIM signature; it's purely additive and doesn't touch your MX records, SPF, or any other DKIM selector your domain already has for its normal mail.

Check status

Once the DNS records are live, check verification status — SES usually confirms within minutes, occasionally up to 72 hours depending on your DNS provider's propagation time.

POST /sender-domains/:id/verify
curl -X POST https://bulkemail-service.intouchvas.io/api/v1/sender-domains/2/verify \
  -H "x-api-key: <your key>"
{
  "id": 2,
  "domain": "yourdomain.com",
  "status": "verified",
  "last_checked_at": "2026-10-15T12:14:30Z"
}

There's no background poller — status only updates when you call this endpoint, so poll it (e.g. every few minutes) until status flips from pending to verified. GET /sender-domains lists every domain on your account with its current status without re-checking SES.

Once verified, any address @yourdomain.com can be used as fromEmail/from_email — e.g. billing@yourdomain.com, no-reply@yourdomain.com — with no further setup.

Restrict allowed senders

By default a verified domain is open — any address at that domain can send. To lock it down to specific addresses only, add them to the allowlist; once at least one address is added, every other address on that domain is rejected.

POST /sender-domains/:id/addresses
curl -X POST https://bulkemail-service.intouchvas.io/api/v1/sender-domains/2/addresses \
  -H "x-api-key: <your key>" \
  -H "Content-Type: application/json" \
  -d '{"email": "billing@yourdomain.com"}'

Send a transactional email

Send a single email, outside any campaign — a receipt, a password reset, a notification.

POST /send

Request body

FieldRequiredDescription
torequiredRecipient email address.
subjectrequiredEmail subject line.
bodyrequiredHTML body.
fromNameoptionalDisplay name for the From address.
fromEmailoptionalDefaults to your account's shared sender. If set, its domain must already be a verified Sender Domain on your account.
callbackUrloptionalWhere to POST delivery-status events for this send — see Delivery callbacks.
curl -X POST https://bulkemail-service.intouchvas.io/api/v1/send \
  -H "x-api-key: <your key>" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "recipient@example.com",
    "subject": "Your receipt",
    "body": "<p>Thanks for your order.</p>",
    "fromName": "intouchvas",
    "callbackUrl": "https://you.example.com/hooks/email"
  }'
const res = await fetch('https://bulkemail-service.intouchvas.io/api/v1/send', {
  method: 'POST',
  headers: {
    'x-api-key': '<your key>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    to: 'recipient@example.com',
    subject: 'Your receipt',
    body: '<p>Thanks for your order.</p>',
    fromName: 'intouchvas',
    callbackUrl: 'https://you.example.com/hooks/email',
  }),
});
const data = await res.json();
import requests

response = requests.post(
    "https://bulkemail-service.intouchvas.io/api/v1/send",
    headers={"x-api-key": "<your key>"},
    json={
        "to": "recipient@example.com",
        "subject": "Your receipt",
        "body": "<p>Thanks for your order.</p>",
        "fromName": "intouchvas",
        "callbackUrl": "https://you.example.com/hooks/email",
    },
)

Response — 200

{
  "status": "success",
  "message": "Queued",
  "messageId": 93201
}

Response — 403, recipient suppressed

{
  "error": "recipient has unsubscribed or previously bounced"
}

Launch a campaign

Launch an already-designed campaign — subject, body, and recipient groups already attached via the console or the Campaigns endpoints — to its recipients. Validates, prices the send, publishes to the queue, and returns 202 immediately; it does not wait for any individual email to go out.

POST /campaigns/:id/send
curl -X POST https://bulkemail-service.intouchvas.io/api/v1/campaigns/42/send \
  -H "x-api-key: <your key>"

Response — 202

{
  "message": "campaign queued for sending",
  "campaign_id": 42,
  "recipient_count": 4820
}

Response — 400, no recipients

{
  "error": "campaign has no recipients"
}

Delivery callbacks

Get notified the moment a send is delivered, bounces, is marked as spam, or is opened/clicked — instead of polling for status. Set a callback URL on the send itself:

  • POST /send — the callbackUrl field, per send.
  • Campaigns — a callback_url field on POST /campaigns or PUT /campaigns/:id, applied to every recipient in that campaign.

Callback payload

We POST this JSON body to your URL for each event, as it happens:

{
  "event": "delivered",
  "sent_email_id": 93201,
  "campaign_id": 42,
  "to_email": "recipient@example.com",
  "status": "delivered",
  "occurred_at": "2026-10-15T14:43:05Z"
}
FieldDescription
eventdelivered · bounced · complained · opened · clicked
campaign_idOmitted for an email sent via /send (no parent campaign).

Errors

Errors are returned as {"error": "message"} with a relevant HTTP status code.

StatusMeaning
400Bad request — missing/invalid fields, or a validation failure (e.g. an empty campaign).
401Missing or invalid API key.
403Your key lacks permission for this action, or the recipient has unsubscribed/bounced previously.
404The campaign or resource doesn't exist on your account.
500Something went wrong on our side — safe to retry.