For the complete documentation index, see llms.txt. This page is also available as Markdown.

Sending invites (email API)

Trigger personalized survey-invite emails from your own systems.

The invite API turns BAI Analytics into the sending arm of your own workflow: your system decides who to email and when (a closed support ticket, a delivered order, a finished onboarding), and BAI Analytics renders the invite template, sends it, tracks delivery, and joins the responses back to your contacts.

The split of responsibilities is deliberate: design lives in the dashboard, triggering lives in the API. The email template, branding, and survey are built in the platform where they can be previewed and reviewed; the API only supplies recipients and variables. That keeps a compromised key from ever rewriting what your customers receive.


Prerequisites

Three things must be true before the first send works. All three are inspectable via GET /sources/{id}/invite-template, so wire that into your setup checks:

  1. A send-scoped API key. Emailing humans is scoped separately from pushing data; all includes it. See Authentication & API keys.

  2. Your organisation's own verified sending domain. API sends never use the shared BAI Analytics sender: automated volume rides your sending reputation, not ours. Until the domain is verified you'll get a SENDER_DOMAIN_NOT_VERIFIED error. Set it up under Organisation details → Email sending (Settings).

  3. An invite template on the source, designed in the platform. The template check returns its available variable keys (say, first_name, order_id) so your integration can validate its data before sending.


The sending flow

1. Check readiness

curl https://boundaryai-ingest-279197672085.europe-west9.run.app/api/input/sources/9021/invite-template \
  -H "Authorization: Bearer $BAI_API_KEY"

Returns whether a template is configured, its variables, sender_domain_verified, sending_enabled, and the day's quota usage.

2. Preview with dry_run

curl -X POST https://boundaryai-ingest-279197672085.europe-west9.run.app/api/input/sources/9021/invites \
  -H "Authorization: Bearer $BAI_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "dry_run": true,
    "recipients": [
      {"email": "jamie@example.com",
       "external_id": "cus_310",
       "variables": {"first_name": "Jamie", "order_id": "A-1042"}}
    ]
  }'

A dry run renders the emails and reports what would happen (would_accept, skipped_already_invited, invalid) without sending anything. Use it in CI and before the first production send.

3. Send

Drop dry_run and the same call returns 202 with a distribution_id. Sends are transactional: 1 to 1,000 recipients per call, each with their own variables. Recipients are appended to the source's respondent list, and each gets a personalized survey link, which is what joins their eventual response back to your external_id.

4. Track the outcome

  • GET /invites/{distribution_id}: overall status and counts (total, sent, failed, skipped).

  • GET /invites/{distribution_id}/recipients: per-recipient outcomes, including the delivery status reported by the mail provider (delivered, bounced, deferred) and your external_id, cursor-paginated.

  • Or skip polling: the invites.completed webhook fires when the distribution finishes, and invite.bounced fires per bounce or spam complaint. See Webhooks.


Safety rails (and why they're not optional)

These exist so an automation bug can't damage your sending reputation, which takes months to rebuild:

  • Never-double-invite by default. An address that already received this survey is skipped; pass resend: true only when you explicitly mean it.

  • Suppression is always enforced. Unsubscribed, bounced, or complaining addresses are never emailed again, even if your system keeps sending them.

  • Rolling 24-hour quota per organisation (default 2,000 invites; raisable on request). The template check shows today's usage, and over-quota sends fail cleanly with INVITE_QUOTA_EXCEEDED rather than queueing.

  • Complaint-rate auto-pause. If spam complaints spike over a 30-day window, sending pauses before mailbox providers penalise your domain.

  • 1,000 recipients per call. Batch bigger lists into multiple calls; each returns its own distribution_id.


Joining responses back to your data

The external_id you set per recipient flows through the whole loop: it's on the recipient outcome rows, on the invite.bounced payload, and, because the survey link is personalized, on the response itself. Use the same identifier you use in feedback pushes (customer_id) and you can connect invited → responded → what they said entirely in your own warehouse.

Last updated