# Splashify Pro Email docs: complete documentation > Official documentation for Splashify Pro Email. Build on the Email API: verify sending identities, send transactional and bulk email, manage templates and suppression, and configure webhooks. Generated from https://email-docs.splashifypro.com. Sections follow the site's own reading order: the guides first, then the API reference and webhooks, then the legal pages. ================================================================================ # Splashify Pro Email API Section: Guides › Documentation URL: https://email-docs.splashifypro.com/ ================================================================================ > Build email-sending applications on Splashify Pro. AWS-SES-shaped API, webhooks, and SMTP relay. # Splashify Pro Email API _Guides and the full API reference for Splashify Pro Email. Verify a domain, send your first email, then add templates, webhooks and the SMTP relay as you need them._ Splashify Pro Email is an email service for developers. The Email API gives you the building blocks to ship transactional and marketing email at scale: verified sending identities, configuration sets, templates, suppression lists, real-time webhooks, and deliverability-grade reputation tracking. The API is shaped like AWS SES. If you've integrated against AWS SES before, you'll feel at home: sending an email, configuring an event destination, or polling send statistics each map onto a familiar endpoint with the same field names. ## Your first email, step by step 1. **Create your account and an API key**: Sign up at [email.splashifypro.com](https://email.splashifypro.com/signup), then generate a key under **Settings → API Keys**. See [Authentication](/getting-started/authentication). 2. **Verify a sending identity**: Prove you own the domain, or the single address, you send from. See [Sending Identities](/knowledge-base/concepts/sending-identities) and [Create identity](/api-reference/identities/create). 3. **Send an email**: One request is enough. Follow the [Quickstart](/getting-started/quick-start), or pick [Node.js](/getting-started/node-quickstart), [Python](/getting-started/python-quickstart), [PHP](/getting-started/php-quickstart), [Go](/getting-started/go-quickstart), [cURL](/getting-started/curl-quickstart) or [SMTP Relay](/getting-started/smtp-quickstart). 4. **See what happened to it**: Get delivery, bounce, open and click events on your own URL. See [Webhooks](/webhooks). 5. **Move out of the sandbox**: Every new account starts in sandbox mode, with a daily sending limit. See [Sandbox vs Production](/knowledge-base/concepts/sandbox). ## Base URL All API requests are made to: ``` https://api.splashifypro.com/api/v1/partner/email ``` ## Authentication Every API request must carry your secret API key in the `Authorization` header: ```bash Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` Generate a key in Splashify Pro Email at [email.splashifypro.com](https://email.splashifypro.com) under **Settings → API Keys**. The key is shown once, so store it in a secure secret manager. > **Security:** Treat your API key like a password. Never embed it in > client-side code, mobile apps, or public repositories. ## Quick example Send a transactional email with two lines of curl: ```bash curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "alerts@yourcompany.com", "to": ["customer@example.com"], "subject": "Your order has shipped", "html_body": "

Tracking: ABC123

", "text_body": "Tracking: ABC123" }' ``` Response: ```json { "success": true, "results": [ { "recipient": "customer@example.com", "message_id": "f9c3a2b1-...", "status": "queued" } ] } ``` ## API surface at a glance | Action | Endpoint | AWS SES equivalent | |---|---|---| | Send transactional | `POST /send` | `SendEmail` | | Send raw MIME | `POST /send-raw` | `SendRawEmail` | | Send templated | `POST /send-template` | `SendTemplatedEmail` | | Bulk templated | `POST /send-bulk` | `SendBulkTemplatedEmail` | | Verify domain / address | `POST /identities` | `CreateEmailIdentity` | | Configuration sets | `/configuration-sets` | `CreateConfigurationSet`... | | Event destinations | `/configuration-sets/:id/event-destinations` | `CreateConfigurationSetEventDestination` | | Templates | `/templates` | `CreateEmailTemplate`... | | Suppression list | `/suppression` | `PutSuppressedDestination`... | | Send quota | `GET /quotas` | `GetSendQuota` | | Send statistics | `GET /stats` | `GetSendStatistics` | | Reputation | `GET /reputation` | `GetAccountReputation` | | Production access | `POST /production-access` | Submit support case | ## Response format Success responses always include `success: true`: ```json { "success": true, "data": { ... } } ``` Error responses carry a stable `error` code + a human-readable `message`: ```json { "success": false, "error": "INVALID_REQUEST", "message": "from address is not on a verified identity" } ``` ## HTTP status codes | Code | Meaning | |---|---| | `200` | Success | | `201` | Resource created | | `400` | Bad request: fix your inputs | | `401` | Missing / invalid API key | | `402` | Insufficient wallet balance: top up | | `403` | Sending paused, sandbox cap reached, or feature locked | | `404` | Resource not found | | `409` | Conflict (duplicate name, etc.) | | `429` | Rate limit hit: back off | | `500` | Server error: retry with backoff | | `503` | Database / dependency unavailable | ## Get started - [Getting Started](/getting-started): First-send walkthrough. - [Concepts](/knowledge-base/concepts): Sending identities, config sets, sandbox. - [API Reference](/api-reference): Every endpoint. - [Webhooks](/webhooks): Receive delivery events. - [Deliverability](/knowledge-base/deliverability): SPF/DKIM/DMARC and reputation. - [Pricing](/knowledge-base/pricing): Flat ₹0.03 per email. - [SMTP Relay](/getting-started/smtp-quickstart): Send from any framework that speaks SMTP. - [Build with AI](/build-with-ai): The MCP server, the SDKs and common recipes. - [Legal](/legal): Terms, privacy and the sending policies. ## Need help? - Read the [FAQ](/knowledge-base/faq) and the [error reference](/knowledge-base/errors). - Email [support@splashifypro.in](mailto:support@splashifypro.in). ================================================================================ # Getting Started Section: Guides › Documentation URL: https://email-docs.splashifypro.com/getting-started ================================================================================ > Send your first email through the Splashify Pro Email API in 5 minutes. # Getting Started This guide walks you through the steps to send your first email through the Splashify Pro Email API. ## Prerequisites 1. A Splashify Pro Email account ([sign up free](https://email.splashifypro.com/signup)) 2. An API key (generated in Splashify Pro Email) 3. A domain you control (for production sends — sandbox sends work without a verified domain but only to addresses you've verified) ## Step 1 — Sign up and get an API key If you don't have an account: 1. Visit [email.splashifypro.com/signup](https://email.splashifypro.com/signup) 2. Enter your email, mobile number (with country code), and a password 3. Verify the OTP sent to **both** your email and WhatsApp 4. Log in To create an API key: 1. Go to **Settings → API Keys** 2. Click **Generate API Key** 3. Copy and securely store the key — it is only shown once 4. Use it as the Bearer token in the `Authorization` header on every API request ## Step 2 — Verify a sending identity Before you can send from an address, you must verify ownership of the domain or the email address itself. Domain verification is preferred because it covers any address at that domain. ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "identity_type": "DOMAIN", "identity_value": "yourcompany.com" }' ``` The response includes the three DNS records you need to publish: ```json { "success": true, "identity_type": "DOMAIN", "identity_value": "yourcompany.com", "status": "PENDING", "dns_records": { "spf": { "type": "TXT", "hostname": "yourcompany.com", "value": "v=spf1 include:_spf.mail.splashifypro.com ~all" }, "dkim": { "type": "CNAME", "hostname": "splashify._domainkey.yourcompany.com", "value": "splashify._domainkey.mail.splashifypro.com" }, "dmarc": { "type": "TXT", "hostname": "_dmarc.yourcompany.com", "value": "v=DMARC1; p=quarantine; rua=mailto:dmarc@splashifypro.com" } } } ``` Publish all three records on your DNS provider and trigger a re-check: ```bash curl -X POST https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com/verify \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` When `"status": "VERIFIED"` comes back, you can send from any address ending in `@yourcompany.com`. ## Step 3 — Send a transactional email ```bash curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome", "html_body": "

Welcome aboard 👋

Thanks for signing up.

", "text_body": "Welcome aboard. Thanks for signing up." }' ``` The response carries the `message_id` you can use to poll delivery status: ```json { "success": true, "results": [ { "recipient": "customer@example.com", "message_id": "550e8400-e29b-41d4-a716-446655440000", "status": "queued" } ] } ``` ## Step 4 — Watch delivery status Poll the message status: ```bash curl https://api.splashifypro.com/api/v1/partner/email/emails/550e8400-e29b-41d4-a716-446655440000 \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Or — better — set up a [webhook](/webhooks) that we POST to whenever the message transitions through `Send → Delivery → Open → Click / Bounce / Complaint`. ## Step 5 — Move out of sandbox New accounts start in **sandbox mode**: - 200 emails/day cap - 1 email/sec peak send rate - Can only send to verified-recipient addresses To go live, request **production access**: ```bash curl -X POST https://api.splashifypro.com/api/v1/partner/email/production-access \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "use_case": "Transactional emails for our SaaS application: signup confirmations, password resets, payment receipts.", "email_volume_estimate": "5000-15000 per day", "has_unsubscribe_method": true, "has_consent_proof": true }' ``` Approved requests lift sandbox + bump your daily quota to 50,000 + peak rate to 14/sec. Most requests are reviewed within 24 business hours. ## Next steps - [**Authentication →**](/getting-started/authentication) — API key best practices - [**Concepts →**](/concepts) — configuration sets, event destinations, suppression - [**Webhooks →**](/webhooks) — real-time delivery events - [**API Reference →**](/api-reference) — full endpoint reference ================================================================================ # Quick Start Section: Guides › Documentation URL: https://email-docs.splashifypro.com/getting-started/quick-start ================================================================================ > Send your first email in under 60 seconds. # Quick Start Send your first email in under 60 seconds. Try the form below — the request fires against your real API key on save. > **Try it on the web page:** `POST /api/v1/partner/email/send` Send a transactional email to one recipient. ## What happens on send ```mermaid sequenceDiagram participant You as Your app participant API as Splashify API participant MX as Recipient MX participant Hook as Your webhook You->>API: POST /partner/email/send API-->>You: 200 { message_id, status: queued } API->>MX: STARTTLS + DKIM-signed message MX-->>API: 250 OK API->>Hook: POST event (Send) API->>Hook: POST event (Delivery) Note over MX,Hook: Bounce / Complaint events follow async ``` The API responds immediately with a `message_id`. Behind the scenes we: 1. **Look up your verified identity.** From-address must be on a verified domain (or be a verified email address). 2. **Check the suppression list.** Recipients on your account's suppression list are rejected with `status: rejected` — no SMTP attempt is made and you're not billed. 3. **Deduct ₹0.03 from your wallet.** First 200/day are free in sandbox. 4. **Sign with DKIM** using a key that resolves through your domain's CNAME at `splashify._domainkey.`. 5. **Connect to the recipient MX over STARTTLS.** 6. **Emit events** — `Send`, then `Delivery` (or `Bounce` / `Complaint`), then `Open` / `Click` if the recipient engages. ## Try it from your terminal ```bash export SPLASHIFY_API_KEY="pk_live_..." curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome", "html_body": "

Hi 👋

Welcome aboard.

" }' ``` ## What's next - **Verify your domain →** [Identities](/api-reference/identities/create) - **Set up webhooks →** [Webhooks](/webhooks) - **Use templates →** [Templates](/api-reference/templates/create) - **Bulk send →** [SendBulk](/api-reference/emails/send-bulk) - **Move out of sandbox →** [Production access](/api-reference/production-access/submit) ================================================================================ # Authentication Section: Guides › Documentation URL: https://email-docs.splashifypro.com/getting-started/authentication ================================================================================ > Bearer-token authentication, API-key security, and rotation. # Authentication The Splashify Pro Email API uses Bearer-token authentication. Every request must carry a valid API key in the `Authorization` header. ## Generating an API key 1. Log in to [email.splashifypro.com](https://email.splashifypro.com) 2. Navigate to **Settings → API Keys** 3. Click **Generate API Key** 4. Copy the key — it is shown **once**. Lose it and you'll need to regenerate. API keys carry the prefix `pk_live_` and are 64 characters long. ## Using your key Set the `Authorization` header on every request: ```http Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` cURL: ```bash curl https://api.splashifypro.com/api/v1/partner/email/quotas \ -H "Authorization: Bearer pk_live_..." ``` Node: ```js fetch("https://api.splashifypro.com/api/v1/partner/email/quotas", { headers: { Authorization: `Bearer ${process.env.SPLASHIFY_API_KEY}` }, }); ``` Python: ```python import requests, os r = requests.get( "https://api.splashifypro.com/api/v1/partner/email/quotas", headers={"Authorization": f"Bearer {os.environ['SPLASHIFY_API_KEY']}"}, ) ``` ## Rate limits API keys are rate-limited per account, not per key. Defaults: - **Sandbox:** 1 send/sec, 200 sends/day - **Production:** 14 sends/sec (configurable per account), 50,000 sends/day (configurable per account) Rate-limit responses come back as `429 Too Many Requests`. Retry with exponential backoff. ## Key security best practices - **Never embed in client-side code.** API keys go on your server, never in browser JS, mobile apps, or public repos. - **Use environment variables.** Most CI / hosting platforms support secret env vars. `.env` files should be `.gitignore`'d. - **Rotate periodically.** Regenerate keys every 90 days at minimum. - **Use one key per environment.** Separate keys for staging / production make blast-radius cleanup easier. ## Revoking a compromised key 1. Go to **Settings → API Keys** 2. Find the compromised key 3. Click **Revoke** Revocation is immediate. New requests with the revoked key get `401 Unauthorized` within ~5 seconds. ## Authentication errors | Status | Code | Cause | |---|---|---| | 401 | `MISSING_AUTH` | No `Authorization` header | | 401 | `INVALID_KEY_FORMAT` | Key doesn't match `pk_live_...` | | 401 | `KEY_NOT_FOUND` | Key was revoked or never existed | | 401 | `KEY_INACTIVE` | Account suspended | | 403 | `IP_BLOCKED` | Caller's IP is on your account's IP allowlist | ================================================================================ # Node.js Quickstart Section: Guides › Quickstarts URL: https://email-docs.splashifypro.com/getting-started/node-quickstart ================================================================================ > Send your first email from Node.js in 60 seconds. # Node.js Quickstart Send transactional and marketing email from Node.js. Works on every runtime — Node 18+, Bun, Deno, and edge environments (Vercel, Cloudflare Workers, etc.). ## 1. Install We don't ship a Node SDK yet — use any HTTP client. `fetch` is built into Node 18+. ```bash # No install needed if you're on Node 18+ ``` ## 2. Set your API key ```bash export SPLASHIFY_API_KEY="pk_live_..." ``` ## 3. Send your first email ```js const res = await fetch( "https://api.splashifypro.com/api/v1/partner/email/send", { method: "POST", headers: { "Authorization": `Bearer ${process.env.SPLASHIFY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "hello@yourcompany.com", to: ["customer@example.com"], subject: "Welcome to our app", html_body: "

Welcome 👋

Your account is ready.

", text_body: "Welcome. Your account is ready.", }), }, ); const data = await res.json(); console.log(data.results[0].message_id); ``` ## 4. Handle errors ```js if (!res.ok) { const err = await res.json(); switch (err.error) { case "INVALID_REQUEST": // Bad input — read err.message break; case "FROM_NOT_VERIFIED": // Verify your domain at /identities first break; case "SUPPRESSED_RECIPIENT": // Recipient is on your suppression list break; case "INSUFFICIENT_BALANCE": // Recharge your wallet break; default: console.error(err.message); } } ``` ## 5. With React Email [React Email](https://react.email) renders HTML email from React components. You author your template as JSX, render it server-side, and pass the HTML to `/send`. ```bash npm install @react-email/components @react-email/render ``` ```jsx import { Html, Button, Text } from "@react-email/components"; import { render } from "@react-email/render"; function Welcome({ name }) { return ( Hi {name}, ); } const html = render(); await fetch("https://api.splashifypro.com/api/v1/partner/email/send", { method: "POST", headers: { "Authorization": `Bearer ${process.env.SPLASHIFY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "hello@yourcompany.com", to: ["customer@example.com"], subject: "Welcome", html_body: html, }), }); ``` ## What's next - [Verify your domain](/api-reference/identities/create) — required before sending in production - [Set up webhooks](/webhooks) — listen to delivery events - [Use templates](/api-reference/templates/create) — reusable bodies with variables - [Send in bulk](/api-reference/emails/send-bulk) — up to 500 recipients per request ================================================================================ # Python Quickstart Section: Guides › Quickstarts URL: https://email-docs.splashifypro.com/getting-started/python-quickstart ================================================================================ > Send your first email from Python in 60 seconds. # Python Quickstart ```bash pip install requests export SPLASHIFY_API_KEY="pk_live_..." ``` ```python import os, requests r = requests.post( "https://api.splashifypro.com/api/v1/partner/email/send", headers={ "Authorization": f"Bearer {os.environ['SPLASHIFY_API_KEY']}", "Content-Type": "application/json", }, json={ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome to our app", "html_body": "

Welcome 👋

", "text_body": "Welcome.", }, ) r.raise_for_status() print(r.json()["results"][0]["message_id"]) ``` ## Handling errors ```python if not r.ok: err = r.json() raise RuntimeError(f"{err['error']}: {err['message']}") ``` ## Async (httpx) ```python import httpx, asyncio async def send(): async with httpx.AsyncClient() as c: r = await c.post( "https://api.splashifypro.com/api/v1/partner/email/send", headers={"Authorization": f"Bearer {API_KEY}"}, json={...}, ) return r.json() asyncio.run(send()) ``` ## What's next - [Verify your domain](/api-reference/identities/create) - [Set up webhooks](/webhooks) - [Use templates](/api-reference/templates/create) ================================================================================ # PHP Quickstart Section: Guides › Quickstarts URL: https://email-docs.splashifypro.com/getting-started/php-quickstart ================================================================================ > Send your first email from PHP in 60 seconds. # PHP Quickstart ```php true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('SPLASHIFY_API_KEY'), 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode([ 'from' => 'hello@yourcompany.com', 'to' => ['customer@example.com'], 'subject' => 'Welcome', 'html_body' => '

Welcome 👋

', 'text_body' => 'Welcome.', ]), ]); $res = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $body = json_decode($res, true); if ($status >= 400) { throw new RuntimeException($body['error'] . ': ' . $body['message']); } echo $body['results'][0]['message_id']; ``` ## Laravel In `config/services.php`: ```php 'splashify' => ['key' => env('SPLASHIFY_API_KEY')], ``` ```php use Illuminate\Support\Facades\Http; Http::withToken(config('services.splashify.key')) ->post('https://api.splashifypro.com/api/v1/partner/email/send', [ 'from' => 'hello@yourcompany.com', 'to' => ['customer@example.com'], 'subject' => 'Welcome', 'html_body' => '

Welcome

', ]) ->throw(); ``` ## What's next - [Verify your domain](/api-reference/identities/create) - [Set up webhooks](/webhooks) ================================================================================ # Go Quickstart Section: Guides › Quickstarts URL: https://email-docs.splashifypro.com/getting-started/go-quickstart ================================================================================ > Send your first email from Go in 60 seconds. # Go Quickstart ```go package main import ( "bytes" "encoding/json" "fmt" "net/http" "os" ) func main() { body, _ := json.Marshal(map[string]any{ "from": "hello@yourcompany.com", "to": []string{"customer@example.com"}, "subject": "Welcome", "html_body": "

Welcome 👋

", "text_body": "Welcome.", }) req, _ := http.NewRequest("POST", "https://api.splashifypro.com/api/v1/partner/email/send", bytes.NewReader(body), ) req.Header.Set("Authorization", "Bearer "+os.Getenv("SPLASHIFY_API_KEY")) req.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() var out struct { Success bool `json:"success"` Results []struct { MessageID string `json:"message_id"` Status string `json:"status"` } `json:"results"` } json.NewDecoder(res.Body).Decode(&out) fmt.Println(out.Results[0].MessageID) } ``` ## What's next - [Verify your domain](/api-reference/identities/create) - [Set up webhooks](/webhooks) ================================================================================ # cURL Quickstart Section: Guides › Quickstarts URL: https://email-docs.splashifypro.com/getting-started/curl-quickstart ================================================================================ > Send your first email with cURL. # cURL Quickstart The fastest way to test an integration. Every endpoint can be hit directly with cURL — useful for debugging, scripts, and CI smoke tests. ## Set your API key ```bash export SPLASHIFY_API_KEY="pk_live_..." ``` ## Send an email ```bash curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome", "html_body": "

Welcome 👋

", "text_body": "Welcome." }' ``` ## Verify a domain ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"identity_type": "DOMAIN", "identity_value": "yourcompany.com"}' ``` ## Check delivery status ```bash curl https://api.splashifypro.com/api/v1/partner/email/emails/$MESSAGE_ID \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Get send statistics ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/stats?days=14' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Pipe through `jq` to format: ```bash curl ... | jq '.stats[] | {date: .day_bucket, sent: .send_count, bounced: .bounced_count}' ``` ================================================================================ # SMTP Relay Section: Guides › Quickstarts URL: https://email-docs.splashifypro.com/getting-started/smtp-quickstart ================================================================================ > Drop into any framework that speaks SMTP — WordPress, Magento, Django, Laravel, Rails, Postfix. # SMTP Relay For frameworks and platforms that can't easily call our REST API, use the SMTP relay. Same DKIM signing, suppression, billing, and webhook delivery — your app just speaks plain SMTP. ## Connection | Setting | Value | |---|---| | Host | `smtp.splashifypro.com` | | Port | `587` (STARTTLS) or `465` (TLS) | | Username | `emailapikey` (literal) | | Password | `pk_live_...` (your API key) | TLS is required. Plain-text auth is rejected. ## Test with swaks ```bash swaks --to customer@example.com \ --from hello@yourcompany.com \ --server smtp.splashifypro.com \ --port 587 -tls \ --auth-user emailapikey \ --auth-password "$SPLASHIFY_API_KEY" \ --header "Subject: Test from swaks" \ --body "Hello" ``` ## WordPress (WP Mail SMTP) 1. Plugin → **WP Mail SMTP** → install 2. Mailer → **Other SMTP** 3. Host: `smtp.splashifypro.com` · Port: `587` · Encryption: `TLS` 4. Auth: ON · Username: `emailapikey` · Password: your API key 5. Save & send a test email ## Django ```python # settings.py EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_HOST = "smtp.splashifypro.com" EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = "emailapikey" EMAIL_HOST_PASSWORD = os.environ["SPLASHIFY_API_KEY"] DEFAULT_FROM_EMAIL = "hello@yourcompany.com" ``` ## Laravel ```env MAIL_MAILER=smtp MAIL_HOST=smtp.splashifypro.com MAIL_PORT=587 MAIL_USERNAME=emailapikey MAIL_PASSWORD=${SPLASHIFY_API_KEY} MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=hello@yourcompany.com ``` ## Node (nodemailer) ```js import nodemailer from "nodemailer"; const transport = nodemailer.createTransport({ host: "smtp.splashifypro.com", port: 587, secure: false, // STARTTLS auth: { user: "emailapikey", pass: process.env.SPLASHIFY_API_KEY, }, }); await transport.sendMail({ from: "hello@yourcompany.com", to: "customer@example.com", subject: "Hello", html: "

Welcome

", }); ``` ## Postfix In `/etc/postfix/main.cf`: ``` relayhost = [smtp.splashifypro.com]:587 smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous smtp_use_tls = yes smtp_tls_security_level = encrypt ``` In `/etc/postfix/sasl_passwd`: ``` [smtp.splashifypro.com]:587 emailapikey:pk_live_... ``` ```bash postmap /etc/postfix/sasl_passwd chmod 600 /etc/postfix/sasl_passwd* postfix reload ``` ## Supabase Auth (transactional email for signups, OTPs, password reset) Supabase ships a "Custom SMTP" panel that you can point at the relay so signup confirmation, magic-link, and password-recovery emails come from your verified sender instead of the Supabase default. **Project → Project Settings → Auth → SMTP Settings:** | Field | Value | |---|---| | Sender email | `noreply@yourcompany.com` *(must be on a verified identity)* | | Sender name | Whatever appears in the inbox From line | | Host | `smtp.splashifypro.com` | | Port | `587` | | Username | `emailapikey` | | Password | your `pk_live_…` API key | | Minimum interval per user | `60` seconds (Supabase default — anti-abuse) | Then save & hit **Send test email**. If you get `535 5.0.0 5.7.0 invalid api key format` it means you pasted something other than a `pk_live_…` (or `sk_live_…` for app-developer accounts) key — copy the key from [Settings → API key](https://email.splashifypro.com/settings) in Splashify Pro Email. ## Things to know - **Sender must be on a verified identity.** Sends from an unverified email/domain are rejected with `550 5.7.1 sender '' is not on a verified identity for this partner`. Add the domain or email at [Settings → Identities](https://email.splashifypro.com/identities) before testing. - **Suppression list applies.** Recipients on your account suppression list are rejected at RCPT TO with `550 5.7.1 recipient on suppression list`. - **Free sandbox: 200 emails/day.** New accounts are sandboxed. Once you exceed the 200/day quota you'll get `452 4.7.0 sandbox daily quota of 200 emails reached`. Request production access from the dashboard to lift it. - **Billing.** ₹0.03/email for paid sends (post-sandbox); sandbox sends are free. SMTP and REST sends bill identically. - **Webhooks fire normally.** SMTP and REST sends produce the same event stream into your configured destinations. - **TLS is required.** Plain-text AUTH is rejected; the relay only advertises AUTH after STARTTLS (port 587) or on the implicit-TLS port (465). - **Per-message metadata via headers.** Set `X-Configuration-Set: ` on the outbound message to attribute the send to a config set. ================================================================================ # AI Onboarding Section: Guides › Build with AI URL: https://email-docs.splashifypro.com/build-with-ai ================================================================================ > Drop this page into your AI assistant for an instant Splashify Pro Email API onboarding. # AI Onboarding Working with an AI coding assistant (Cursor, Claude Code, ChatGPT, Windsurf, etc.)? Paste this page's URL into your assistant — we've formatted everything below for an LLM to ingest in one shot. For Cursor / Claude Code / Windsurf, run: ``` https://email-docs.splashifypro.com/getting-started/ai-onboarding ``` ## You are integrating: Splashify Pro Email API You are a developer integration assistant. You are helping a user build against the **Splashify Pro Email API**. The API surface is **AWS-SES-shaped** — endpoint shapes, response field names, and event payloads are aligned with AWS SES so SES integrators feel at home. ## Base URL ``` https://api.splashifypro.com/api/v1/partner/email ``` ## Authentication Every request requires a Bearer API key in the `Authorization` header. Keys are prefixed `pk_live_`. Generate from [email.splashifypro.com](https://email.splashifypro.com) → **Settings → API Keys**. ``` Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` ## Core concepts - **Identity:** Verified domain or email address. Required before you can send `From:` that address. Domain identities cover any address at the domain. Verified via 3 DNS records (SPF + DKIM CNAME + DMARC). - **Configuration Set:** A logical grouping of sends. Attach event destinations (webhooks) to a config set; sends specify `configuration_set_name` to route events. AWS-style. - **Event Destination:** Webhook URL on a config set. Receives the AWS-SES-shaped JSON event payload signed with HMAC-SHA256. - **Template:** Reusable email body with `{{variable}}` placeholders. Send via `POST /send-template` or `POST /send-bulk`. - **Suppression list:** Account-level. Hard bounces + complaints + unsubscribes auto-add. Sends to suppressed addresses are rejected pre-SMTP. - **Sandbox:** Default state for new accounts. 200/day cap, 1 send/sec, recipient must be verified. Request production access to lift. - **Wallet:** Prepaid by default. ₹0.03 per email. First 200/day in sandbox are free. Recharge in Splashify Pro Email. ## Most-used endpoints ### Send transactional email ```bash POST /api/v1/partner/email/send { "from": "hello@yourcompany.com", "to": ["user@example.com"], "subject": "Hello", "html_body": "

Hi

", "text_body": "Hi", "configuration_set_name": "production", "category": "transactional" } ``` Response: `{"success":true,"results":[{"recipient":"user@example.com","message_id":"","status":"queued"}]}` ### Send templated email ```bash POST /api/v1/partner/email/send-template { "from": "hello@yourcompany.com", "to": ["user@example.com"], "template_name": "welcome", "variables": {"first_name": "Alex"} } ``` ### Bulk templated send (up to 50 recipients × 50 destinations / 500 total) ```bash POST /api/v1/partner/email/send-bulk { "from": "hello@yourcompany.com", "template_name": "newsletter", "default_template_data": {"campaign": "june"}, "destinations": [ { "to": ["a@example.com"], "replacement_data": {"first_name": "Alex"} }, { "to": ["b@example.com"], "replacement_data": {"first_name": "Brett"} } ] } ``` ### Get message status ```bash GET /api/v1/partner/email/emails/{message_id} ``` ### Verify a sending identity (domain) ```bash POST /api/v1/partner/email/identities { "identity_type": "DOMAIN", "identity_value": "yourcompany.com" } ``` Response includes the 3 DNS records to publish (SPF TXT, DKIM CNAME, DMARC TXT). After publishing, trigger: ```bash POST /api/v1/partner/email/identities/DOMAIN/yourcompany.com/verify ``` ### Create a configuration set ```bash POST /api/v1/partner/email/configuration-sets { "name": "production", "suppression_options": "BOUNCE_AND_COMPLAINT" } ``` ### Add a webhook event destination ```bash POST /api/v1/partner/email/configuration-sets/{config_set_id}/event-destinations { "name": "production-webhook", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/splashify", "webhook_secret": "your-shared-secret", "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"] } ``` ### Suppression list ```bash GET /api/v1/partner/email/suppression PUT /api/v1/partner/email/suppression/{email} DELETE /api/v1/partner/email/suppression/{email} ``` ### Quotas + reputation ```bash GET /api/v1/partner/email/quotas # daily cap, sandbox, reputation_status GET /api/v1/partner/email/stats # day-by-day counters GET /api/v1/partner/email/reputation # 14d bounce/complaint rate GET /api/v1/partner/email/events # event log ``` ## Webhook payload shape (AWS-SES-style) ```json { "eventType": "Delivery", "mail": { "timestamp": "2026-05-03T12:34:56Z", "messageId": "", "source": "hello@yourcompany.com", "destination": ["user@example.com"] }, "delivery": { "timestamp": "2026-05-03T12:34:57Z", "recipients": ["user@example.com"], "smtpResponse": "250 OK" } } ``` Headers: - `X-Splashify-Event` — `Send|Delivery|Bounce|Complaint|Open|Click|Reject|RenderingFailure|DeliveryDelay` - `X-Splashify-Signature` — `sha256=` HMAC-SHA256 of raw body, key = your `webhook_secret` - `X-Splashify-Timestamp` — Unix seconds - `X-Splashify-Delivery-ID` — UUID per delivery attempt (use for idempotency) Verify the signature in constant time, dedupe on Delivery-ID, return `200 OK` to ack. 4xx = no retry. 5xx + timeout = retry per `{1min, 5min, 15min}`. ## Sandbox vs production Sandbox limits: - 200 emails / day - 1 email / second - Can only send to addresses you've verified Request production access: ```bash POST /api/v1/partner/email/production-access { "use_case": "Transactional emails for our SaaS — signup confirms, password resets, payment receipts", "email_volume_estimate": "5000-15000 per day", "has_unsubscribe_method": true, "has_consent_proof": true } ``` Approval lifts sandbox + bumps daily cap to 50,000 + peak rate to 14/sec. ## Pricing - ₹0.03 per email, flat - First 200/day free in sandbox - Custom per-account rates supported (set by our team) ## Errors All errors are `{success: false, error: "", message: ""}` with a 4xx or 5xx status: - `400` — bad request (read `message`) - `401` — invalid / missing API key - `402` — wallet balance insufficient (recharge) - `403` — sandbox cap, sending paused, IP blocked - `404` — not found - `429` — rate limit (back off) ## Where to read more - Full API reference: https://email-docs.splashifypro.com/api-reference - Webhooks: https://email-docs.splashifypro.com/webhooks - Deliverability: https://email-docs.splashifypro.com/deliverability - Knowledge base: https://email-docs.splashifypro.com/concepts That's everything an AI agent needs to start integrating. If your assistant asks about something not covered here, link it to the relevant section above. ================================================================================ # MCP Server Section: Guides › Build with AI URL: https://email-docs.splashifypro.com/build-with-ai/mcp-server ================================================================================ > Connect Claude, Cursor, and other AI assistants to the Splashify Pro Email API via Model Context Protocol. # MCP Server The **Splashify Pro MCP server** lets your AI assistant (Claude Desktop, Cursor, Windsurf, Claude Code, etc.) call the Email API directly. Send emails, verify identities, configure webhooks — all from a chat conversation. [Model Context Protocol](https://modelcontextprotocol.io) is the open standard Anthropic shipped for connecting AI tools to external APIs. Splashify Pro hosts an MCP server that exposes every public endpoint as a tool the assistant can call. ## Endpoint The MCP server is **hosted** — there's nothing to install locally. Point your AI client at the SSE endpoint and authenticate with your Email API key: ``` URL: https://mcp.splashifypro.com/sse Auth: Authorization: Bearer pk_live_... ``` Use the same `pk_live_…` key you use for the REST API (generate one at [email.splashifypro.com](https://email.splashifypro.com) → Settings → API Key). The MCP server uses the same auth chain, permission scope, and rate-limit budget as REST. ## Add to Claude Desktop Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```json { "mcpServers": { "splashifypro": { "type": "sse", "url": "https://mcp.splashifypro.com/sse", "headers": { "Authorization": "Bearer pk_live_..." } } } } ``` Restart Claude Desktop. You'll see "splashifypro" in the bottom-left tools menu. ## Add to Cursor Edit `.cursor/mcp.json` in your project root: ```json { "mcpServers": { "splashifypro": { "type": "sse", "url": "https://mcp.splashifypro.com/sse", "headers": { "Authorization": "Bearer pk_live_..." } } } } ``` ## Add to Claude Code Edit `~/.claude/settings.json` or your project's `.mcp.json`: ```json { "mcpServers": { "splashifypro": { "type": "sse", "url": "https://mcp.splashifypro.com/sse", "headers": { "Authorization": "Bearer pk_live_..." } } } } ``` ## Add to Windsurf Edit `~/.codeium/windsurf/mcp_config.json`. Same JSON shape as Cursor. ## Available tools The MCP server exposes 35+ tools, one per Email API endpoint: | Category | Tools | |---|---| | Send | `partner_email_send`, `partner_email_send_template`, `partner_email_send_bulk`, `partner_email_send_raw`, `partner_email_get_status` | | Identities | `partner_email_list_identities`, `partner_email_create_identity`, `partner_email_get_identity`, `partner_email_verify_identity`, `partner_email_delete_identity` | | Configuration sets | `partner_email_list_configuration_sets`, `partner_email_create_configuration_set`, `partner_email_get_configuration_set`, `partner_email_delete_configuration_set` | | Event destinations | `partner_email_create_event_destination` | | Templates | `partner_email_list_templates`, `partner_email_create_template`, `partner_email_delete_template`, `partner_email_preview_template` | | Suppression | `partner_email_list_suppression`, `partner_email_add_suppression`, `partner_email_remove_suppression` | | Stats + reputation | `partner_email_get_quotas`, `partner_email_get_stats`, `partner_email_get_reputation`, `partner_email_list_events`, `partner_email_get_bounce_report` | | Production access | `partner_email_list_production_access_requests`, `partner_email_submit_production_access` | | Dedicated IP | `partner_email_get_dedicated_ip_request`, `partner_email_request_dedicated_ip`, `partner_email_cancel_dedicated_ip_request` | | Account + security | `partner_email_list_activity_logs`, `partner_email_list_ip_allowlist`, `partner_email_add_ip_allowlist_entry`, `partner_email_remove_ip_allowlist_entry` | ## Example prompts > "Send a welcome email to alex@example.com from hello@mycompany.com" The assistant calls `partner_email_send` with the right shape, hands the `message_id` back to you, and offers to follow up via `partner_email_get_status`. > "Verify the domain mycompany.com and tell me which DNS records I need" `partner_email_create_identity` is called, the response includes the SPF / DKIM / DMARC records, and the assistant explains where to publish them. > "Why are 5% of my emails bouncing?" `partner_email_get_reputation` + `partner_email_list_events?event_type=bounce` fire in parallel; the assistant correlates the bounces against recipients and suggests fixes. ## Security - **Hosted, not local.** Your API key never leaves your machine except as a Bearer header on outbound HTTPS requests to `mcp.splashifypro.com` — same path your REST calls already take. - **Mutating tools confirm first.** Tools that change state (`partner_email_send`, `partner_email_create_*`, `partner_email_delete_*`) generally require the assistant to read back the action; you approve before they fire. - **Audit log.** Every MCP-driven call shows up at [email.splashifypro.com](https://email.splashifypro.com) → Activity Log alongside REST + SDK calls so you can see who/what fired which endpoint when. - **Rate limits.** MCP calls share the same per-key budget as REST. Burst protection kicks in identically. ## Troubleshooting - **"splashifypro server not found":** check the JSON config path + restart the host app. SSE transport requires the host app to support remote MCP (Claude Desktop ≥ 0.7, Cursor ≥ 0.42, Claude Code ≥ 1.0). - **`401 invalid_key`:** API key is wrong or revoked. Generate a fresh one in Splashify Pro Email. - **`402 insufficient_balance`:** wallet is empty. Recharge from [Splashify Pro Email](https://email.splashifypro.com/wallet). - **`429 rate_limited`:** assistant is firing too many requests too fast — back off or apply for production access to lift the per-second cap. ## Feedback + bugs Spotted a bug or want a tool that isn't listed? Email **support@splashifypro.in** with the prompt that triggered it and your `pk_live_` key prefix (first 12 chars). We ship MCP fixes weekly. ================================================================================ # SDKs Section: Guides › Build with AI URL: https://email-docs.splashifypro.com/build-with-ai/sdks ================================================================================ > Official SDKs for Node.js, Python, and PHP — auto-generated from our OpenAPI spec. # SDKs Official SDKs ship for **Node.js**, **Python**, and **PHP**. All three are auto-generated from the same OpenAPI spec the API runs against, so they stay in lock-step with the platform. | Language | Package | Source | |---|---|---| | Node.js | `@splashifypro/sdk` | [github.com/splashifypro/sdk-node](https://github.com/splashifypro/sdk-node) | | Python | `splashifypro` | [github.com/splashifypro/sdk-python](https://github.com/splashifypro/sdk-python) | | PHP | `splashifypro/sdk` | [github.com/splashifypro/sdk-php](https://github.com/splashifypro/sdk-php) | Don't see your language? The API is plain HTTP/JSON — every endpoint can be called with the language's stdlib HTTP client. See the per-language [Quickstarts](/getting-started/node-quickstart) for hand-rolled examples. ## Node.js ```bash npm install @splashifypro/sdk ``` ```js import { SplashifyClient } from "@splashifypro/sdk"; const client = new SplashifyClient({ apiKey: process.env.SPLASHIFY_API_KEY, }); const result = await client.emails.send({ from: "hello@yourcompany.com", to: ["customer@example.com"], subject: "Welcome", htmlBody: "

Welcome

", }); console.log(result.results[0].messageId); ``` TypeScript types ship with the package. Edge runtimes (Vercel, Cloudflare Workers, Deno) are supported. ## Python ```bash pip install splashifypro ``` ```python from splashifypro import SplashifyClient client = SplashifyClient(api_key=os.environ["SPLASHIFY_API_KEY"]) result = client.emails.send( from_="hello@yourcompany.com", to=["customer@example.com"], subject="Welcome", html_body="

Welcome

", ) print(result["results"][0]["message_id"]) ``` Async client also available: ```python from splashifypro import AsyncSplashifyClient async with AsyncSplashifyClient(api_key=...) as client: result = await client.emails.send(...) ``` ## PHP ```bash composer require splashifypro/sdk ``` ```php use Splashifypro\Client; $client = new Client(getenv('SPLASHIFY_API_KEY')); $result = $client->emails->send([ 'from' => 'hello@yourcompany.com', 'to' => ['customer@example.com'], 'subject' => 'Welcome', 'html_body' => '

Welcome

', ]); echo $result['results'][0]['message_id']; ``` Laravel users can pull in our facade by registering the package's service provider — see the README on [github.com/splashifypro/sdk-php](https://github.com/splashifypro/sdk-php). ## Versioning SDKs follow [semantic versioning](https://semver.org). Major version bumps only happen for breaking changes; the API itself is versioned under `/api/v1/` and we'll ship `/api/v2/` before any breaking contract change so the SDK can support both. ## Reporting issues Each SDK lives in its own repo and accepts issues + PRs: - [github.com/splashifypro/sdk-node/issues](https://github.com/splashifypro/sdk-node/issues) - [github.com/splashifypro/sdk-python/issues](https://github.com/splashifypro/sdk-python/issues) - [github.com/splashifypro/sdk-php/issues](https://github.com/splashifypro/sdk-php/issues) For platform-side bugs (the API misbehaving regardless of SDK), or for anything you can't reduce to a single language, email **support@splashifypro.in** with the request payload + the `pk_live_` key prefix (first 12 chars). ================================================================================ # Common Recipes Section: Guides › Build with AI URL: https://email-docs.splashifypro.com/build-with-ai/recipes ================================================================================ > Curated patterns for shipping email features fast. # Common Recipes Production-grade patterns that save you reinventing the wheel. ## Idempotent transactional sends Replays of the same logical send (e.g. payment-receipt for the same charge ID) shouldn't trigger duplicate emails. Stamp a stable `X-Idempotency-Key` header derived from your business key, and de-dup on your side before calling `/send`: ```js const sentKey = await redis.get(`email:sent:${chargeId}`); if (sentKey) return; // already emailed const res = await client.emails.send({...}); await redis.set(`email:sent:${chargeId}`, res.results[0].messageId, { EX: 86400 }); ``` We don't currently honor an `Idempotency-Key` header server-side (roadmap), so the dedup happens at your layer. ## Per-recipient personalization at scale For bulk sends with per-recipient variables, use `/send-bulk`: ```js await client.emails.sendBulk({ from: "hello@yourcompany.com", templateName: "newsletter-june", defaultTemplateData: { campaign: "june-2026" }, destinations: users.map(u => ({ to: [u.email], replacementData: { first_name: u.firstName, unsubscribe_url: `https://yoursite.com/u/${u.token}`, }, })), }); ``` 50 destinations × 50 recipients × 500 total per request. For larger volumes, chunk into multiple calls — there's no per-account rate limit on bulk-send concurrency, only the per-account per-second peak rate. ## Dynamic from-name Set the `from` field as `"Display Name "` and recipients see "Display Name" in their inbox: ```json { "from": "Sarah from Acme ", ... } ``` Domain still has to be verified. Display name is unverified — recipients see whatever you put there. ## Custom MAIL FROM domain (return-path) Sets the bounce return-path to a custom subdomain so DMARC alignment includes both DKIM and SPF. Lands on roadmap. Until then, the return-path is `bounces@mail.splashifypro.com` and DMARC alignment relies on DKIM only (`p=quarantine` is fine; `p=reject` may need DMARC relaxed alignment). ## Per-customer attribution If you're sending on behalf of multiple downstream customers, create a configuration set per customer and reference it on every send: ```js await client.emails.send({ from: "alerts@yourcompany.com", to: ["customer@example.com"], configurationSetName: "customer_acme_corp", ... }); ``` Stats roll up per config set — `GET /stats?config_set_id=...`. Each config set can also have its own webhook destination so events for Acme go to one URL and events for Globex go to another. ## Hard-bounce auto-list-cleaning Hard bounces are added to your suppression list automatically. To keep your application's email list in sync, listen for the `Bounce` webhook event: ```js app.post("/webhooks/splashify", async (req, res) => { const sig = req.header("x-splashify-signature"); if (!verifyHMAC(req.rawBody, sig, process.env.SPLASHIFY_WEBHOOK_SECRET)) { return res.status(401).end(); } if (req.body.eventType === "Bounce" && req.body.bounce.bounceType === "Permanent") { const email = req.body.bounce.bouncedRecipients[0].emailAddress; await db.users.updateOne({ email }, { $set: { emailBouncedHard: true } }); } res.status(200).end(); }); ``` Now your signup form / re-engagement campaigns can skip these addresses up-front instead of burning send quota. ## Retry on 5xx Network blips and brief upstream issues should retry; auth/quota errors shouldn't. Pseudocode: ```js async function sendWithRetry(payload, attempts = 3) { for (let i = 0; i < attempts; i++) { const res = await client.emails.send(payload); if (res.success) return res; const code = res.error; // Don't retry these — won't get better with time. if (["INVALID_REQUEST", "FROM_NOT_VERIFIED", "INSUFFICIENT_BALANCE", "MISSING_AUTH"].includes(code)) { throw new Error(`${code}: ${res.message}`); } // Backoff on the rest. await sleep(1000 * Math.pow(2, i)); } throw new Error("send_failed_after_retries"); } ``` ## Webhooks that survive your deploys Stamp every event in your local DB before processing — duplicate webhook deliveries (which happen on retries) are idempotent: ```js const eventID = req.header("x-splashify-delivery-id"); const inserted = await db.events.insertOne({ _id: eventID, ...req.body, }, { ignoreDuplicates: true }); if (!inserted.insertedCount) return res.status(200).end(); // dedup // ... process ``` `X-Splashify-Delivery-ID` is a fresh UUID per delivery attempt — even a retried event keeps the same ID. ## Cold-start IP warm-up New production accounts inherit warm sending infrastructure with established reputation across major mailbox providers. You don't need to manually warm up. Dedicated IPs (roadmap) require warm-up — typically 2 weeks of gradually increasing volume. We'll publish a warm-up calculator when dedicated IPs ship. ================================================================================ # Knowledge Base Section: Guides › Knowledge Base URL: https://email-docs.splashifypro.com/knowledge-base ================================================================================ > Concepts, deliverability guides, pricing, errors, and FAQ. # Knowledge Base Long-form guides + reference material that goes deeper than the endpoint docs. Read these when you want to understand WHY the API works the way it does — or when you're debugging deliverability. ## Topics - [**Concepts**](/knowledge-base/concepts) — sending identities, configuration sets, suppression lists, sandbox vs production, reputation - [**Deliverability**](/knowledge-base/deliverability) — SPF / DKIM / DMARC, IP warm-up, content best practices, sender reputation - [**Pricing**](/knowledge-base/pricing): flat ₹0.03 per email, sandbox free tier, billing model - [**Errors**](/knowledge-base/errors) — every error code, what it means, how to fix it - [**FAQ**](/knowledge-base/faq) — common questions ## Quick orientation If you're new, read these in order: 1. [Sending identities](/knowledge-base/concepts/sending-identities) 2. [Configuration sets](/knowledge-base/concepts/configuration-sets) 3. [Sandbox vs production](/knowledge-base/concepts/sandbox) 4. [SPF / DKIM / DMARC](/knowledge-base/deliverability/spf-dkim-dmarc) 5. [Pricing](/knowledge-base/pricing) ================================================================================ # Deliverability Section: Guides › Knowledge Base URL: https://email-docs.splashifypro.com/knowledge-base/deliverability ================================================================================ > Get your email into the inbox — SPF, DKIM, DMARC, content best practices, sender reputation. # Deliverability Sending email isn't enough. **Inboxing** is. Mailbox providers (Gmail, Outlook, Yahoo, Apple Mail, etc.) decide whether your message lands in inbox, junk, or gets refused based on a stack of signals — domain authentication, sender reputation, content patterns, recipient engagement. This page is the field guide. ## The 90% rule Most deliverability problems come from one of three causes: 1. **Authentication is broken** — SPF/DKIM/DMARC misconfigured → provider can't verify the sender → marks as spam. 2. **List quality is bad** — too many bounces (sending to dead addresses) or too many complaints (recipients didn't expect the email). 3. **Content tripped a spam filter** — links in the body to blocklisted domains, misleading subject lines, missing plaintext alternative. Get authentication right + send to opt-in lists + don't write spammy copy and you'll inbox. ## SPF / DKIM / DMARC The three DNS-level authentication mechanisms every modern inbox provider expects. ### SPF (Sender Policy Framework) A TXT record on your domain that lists IPs / providers authorized to send mail "from" your domain. We give you: ``` TXT yourcompany.com "v=spf1 include:_spf.mail.splashifypro.com ~all" ``` The `include:` mechanism delegates SPF lookup to our published record, so when our IPs change you don't have to update yours. ### DKIM (DomainKeys Identified Mail) A cryptographic signature in the email header that lets the receiver verify the message wasn't tampered with in transit. We publish the public key under our domain and you publish a CNAME that points at it: ``` CNAME splashify._domainkey.yourcompany.com splashify._domainkey.mail.splashifypro.com ``` This way you don't manage private keys + we can rotate the key periodically without coordinating with every customer. ### DMARC (Domain-based Message Authentication, Reporting & Conformance) DMARC sits on top of SPF + DKIM. It tells the receiver what to do with unauthenticated mail claiming to be from your domain: ``` TXT _dmarc.yourcompany.com "v=DMARC1; p=quarantine; rua=mailto:dmarc@splashifypro.com" ``` | Policy | Behaviour | |---|---| | `p=none` | Monitor only — receivers report but don't act | | `p=quarantine` | Send to spam (recommended) | | `p=reject` | Refuse outright (strongest, but risky if any legitimate sender isn't authenticated) | The `rua=` address receives aggregate reports. We provide a public endpoint at `dmarc@splashifypro.com` so you don't need to set up your own. ### Verify all three pass ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Response includes per-record `pass: true/false`: ```json { "dns_records": { "spf": { "pass": true, "found": "v=spf1 include:_spf.mail.splashifypro.com ~all" }, "dkim": { "pass": true, "found": "CNAME splashify._domainkey.mail.splashifypro.com" }, "dmarc": { "pass": true, "found": "v=DMARC1; p=quarantine; rua=mailto:..." } } } ``` ## List hygiene Bounces and complaints are the #2 cause of deliverability decline. ### Acquire opt-in addresses only Single opt-in (email entered on a form, no confirmation step) is the minimum. Double opt-in (form + confirmation email + click the link) is the gold standard — drops bounce rates ~10x. Don't: - Buy lists - Scrape websites - Import a list of "all my contacts" from a co-founder's old job - Email people who gave you their card at a conference (without saying "we'll add you to our newsletter") ### Bounce + complaint handling Both are auto-managed by the [suppression list](/knowledge-base/concepts/suppression). Hard bounces and complaints get added immediately, and we never attempt to send to suppressed addresses. Sync to your application: - `Bounce` webhook event → mark user `email_bounced=true` in your DB - `Complaint` webhook event → mark user `email_complained=true` in your DB Skip these users from any future outbound — your suppression list is mirrored at our level, but having it locally lets you also skip them from marketing campaigns + product onboarding flows. ### Engagement-based pruning Mailbox providers weight engagement heavily. If a recipient hasn't opened or clicked any of your emails in 6 months, sending to them hurts your reputation. Drop them from active campaigns until they re-engage (e.g. via a "we miss you" prompt). ## Content best practices | Do | Don't | |---|---| | Plain `From:` (`hello@yourcompany.com`) | Display-name-only fakery (`Hello `) | | Clear subject (no `RE:` / `FWD:` if not actually a reply) | All-caps, all-emojis, money symbols | | Both HTML + plaintext body | HTML only — spam filters penalize | | Unsubscribe link in marketing email | Marketing email without unsubscribe (illegal in most jurisdictions) | | Image alt text | Image-only emails (heavy spam signal) | | Concise body | 50% link / 50% text ratio | We auto-generate plaintext alternative from your HTML if you don't provide one. We also auto-inject the unsubscribe link if your template doesn't include one (CAN-SPAM compliance). ## Sender reputation We track [reputation](/knowledge-base/concepts/reputation) at the account level. Bounce rate + complaint rate over rolling 14 days. Above-threshold rates trigger automatic warnings + eventual auto-pause. The platform's sending infrastructure is well-warmed and has good standing across major mailbox providers. You inherit that reputation when you start sending — but bad behaviour from your account hurts the broader platform reputation, which is why we're strict about list quality. ## Subdomain strategy For organisations sending high volume of mixed mail types, use subdomains to isolate reputation: | Domain | Use | |---|---| | `mail.acme.com` | Transactional (signup, receipts, password reset) | | `news.acme.com` | Marketing campaigns / newsletters | | `notify.acme.com` | App notifications (high frequency, low engagement) | Each gets its own verified identity. Bounces / complaints on `news.acme.com` don't drag down `mail.acme.com`'s reputation. ## Read more - [SPF / DKIM / DMARC explainer](/knowledge-base/concepts/sending-identities) - [Reputation thresholds + auto-pause](/knowledge-base/concepts/reputation) - [Suppression list mechanics](/knowledge-base/concepts/suppression) ================================================================================ # Pricing Section: Guides › Knowledge Base URL: https://email-docs.splashifypro.com/knowledge-base/pricing ================================================================================ > Flat ₹0.03 per email. No tiers, no commitments, sandbox is free. # Pricing We keep it simple: one rate for everyone, sandbox free, prepaid wallet, no monthly minimums. ## Headline | Tier | Rate | |---|---| | **Sandbox (default for new accounts)** | First 200/day **free**, then ₹0.03/email | | **Production** | ₹0.03/email from email #1 | That's it. No marketing-vs-transactional split. No volume tiers that kick in at obscure thresholds. Same price for HTML, plaintext, template, raw MIME, send-bulk, all of it. ## Currency + GST Pricing is in **INR**. Indian customers are billed with 18% GST on top. Non-India customers are billed in USD the same way, with no GST applied. ## Wallet model The Splashify Pro Email API runs on a **prepaid wallet**: 1. Recharge your wallet in Splashify Pro Email (`email.splashifypro.com` → Wallet → Recharge) 2. Each successful send deducts ₹0.03 (or your override rate) from the wallet balance 3. When balance hits zero, `/send` returns `402 INSUFFICIENT_BALANCE` until you recharge Pay by UPI, card, netbanking or wallet. You get a GST invoice for every recharge, emailed automatically and downloadable from the panel. ## What counts as a billable send A send is billable when: - The API call validates successfully - The recipient is NOT on your suppression list - We attempt SMTP delivery (250 OK or any 4xx/5xx response) NOT billable: - API rejections (`400 INVALID_REQUEST`, `400 FROM_NOT_VERIFIED`) - Suppression-list rejections (`status: rejected` in send response) - Sandbox sends within the daily 200 free quota - Rate-limit rejections (`429`) ## Volume discounts Default is one rate. For customers committing to high steady-state volume, custom rates are negotiable. Reach out via the support form on the panel. Our team can set custom marketing and transactional rates on your account. Once set, those rates take precedence over the default ₹0.03. ## Tracking spend Every send writes a row to your wallet billing log, which you can see at: ``` email.splashifypro.com → Wallet → Transaction history ``` Each row shows the recipient, message_id, rate at send-time, and balance before/after. Same data is exposed via API: ```bash curl 'https://api.splashifypro.com/api/v1/wallet/transactions/$PARTNER_ID' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Recharge minimums Minimum recharge is ₹500. Wallet balance can drop below ₹500 between recharges. We don't gate sends on balance until it hits exactly zero. ## Dedicated IP For customers sending high steady-state volume (typically 10K+/day), a dedicated sending IP isolates your reputation from the shared pool. Request one in Splashify Pro Email under **Dedicated IP**. | Item | Rate | |---|---| | **Dedicated IP** | **₹350 / month per IP** | Charged on a monthly recurring invoice from the date the IP is assigned. Per-email send pricing (₹0.03) does not change: a dedicated IP is only an add-on. Cancel anytime; billing stops at the end of the current billing month and the IP is returned to the shared pool. ## Postpaid (legacy) If you're an older customer on a postpaid wallet (`wallet=Post Paid`), sends accrue against your `outstanding` balance up to your `credit_limit`. Settled monthly with an invoice. Newer accounts ship as prepaid by default. Postpaid is grandfathered for existing customers. ## What we don't charge for - Verifying identities - Creating configuration sets / templates / event destinations - Webhook deliveries to your endpoint - Suppression list management - Reading stats / quotas / events - API rate limit when you stay under the per-second peak The wallet only deducts on **actual sends**. ## Invoices + GST documents Every recharge generates: - A GST invoice (PDF, downloadable from Splashify Pro Email) - An automatic email to your account email - The payment marked as paid once the wallet credit lands For India-based customers with a GSTIN, the invoice carries your GSTIN + state code, usable for input-tax-credit reconciliation. ## Refunds - **Wallet balance** is non-refundable as cash. Once recharged, the balance is yours to spend on email sends. - **Failed sends** (4xx/5xx) are not billed in the first place. - **Mistaken duplicate recharges:** contact support and we'll refund or credit the duplicate. - **Account closure:** unused balance can be donated to a future account with the same email or refunded under exceptional circumstances. Contact support. ## Comparison | Provider | Per-email rate | Free tier | |---|---|---| | **Splashify Pro** | ₹0.03 | 200/day in sandbox | | AWS SES (sending alone) | ~$0.0001 (~₹0.008) | 62K/month from EC2 | | Resend | ~$0.0001 (~₹0.008) | 100/day | | Postmark | ~$0.0015 (~₹0.12) | 100/month | | SendGrid | ~$0.0007–$0.001 | 100/day | We come in cheaper than Postmark and SendGrid, with extra benefits (panel, support, simpler onboarding) layered on top. ================================================================================ # Errors Section: Guides › Knowledge Base URL: https://email-docs.splashifypro.com/knowledge-base/errors ================================================================================ > Every API error code, what it means, and how to fix it. # Errors Every error from the Email API has a stable `error` code + a human-readable `message`. Build retry / error-handling logic against the code, not the message. ## Response shape ```json { "success": false, "error": "INSUFFICIENT_BALANCE", "message": "Wallet balance ₹0.00. Recharge to continue sending." } ``` `success: false` is always present. `error` is the stable code. `message` is for display + may change for clarity over time. ## 400 Bad Request | Code | Cause | Fix | |---|---|---| | `INVALID_REQUEST` | Malformed JSON or missing required field | Read `message` | | `INVALID_AMOUNT` | Non-positive amount on a wallet recharge | Pass amount > 0 | | `INVALID_PARAM` | Path / query param doesn't parse | Check the URL | | `MISSING_PARAM` | Required param missing | Read `message` | | `FROM_NOT_VERIFIED` | `from` address not on a verified identity | Verify domain via `POST /identities` | | `BILLING_INCOMPLETE` | Account profile missing required fields | Fill `PUT /partner/self/billing` | | `BILLING_NOT_SET_UP` | Zoho customer not yet created | Save billing once via `PUT /partner/self/billing` | | `INVALID_SIGNATURE` | HMAC check on payment-verify failed | Don't tamper with payment widget output | | `BAD_RECIPIENT` | Recipient address malformed | Validate before send | | `TOO_MANY_RECIPIENTS` | Per-message recipient cap exceeded (50) | Split into multiple sends | ## 401 Unauthorized | Code | Cause | Fix | |---|---|---| | `MISSING_AUTH` | No `Authorization` header | Add `Authorization: Bearer pk_live_...` | | `INVALID_KEY_FORMAT` | Key doesn't match `pk_live_...` | Regenerate in Splashify Pro Email | | `KEY_NOT_FOUND` | Key was revoked or never existed | Regenerate | | `KEY_INACTIVE` | Account suspended | Contact support | ## 402 Payment Required | Code | Cause | Fix | |---|---|---| | `INSUFFICIENT_BALANCE` | Wallet balance < send price | Recharge wallet | ## 403 Forbidden | Code | Cause | Fix | |---|---|---| | `IP_BLOCKED` | Your IP isn't on your account's IP allowlist | Add to allowlist or call from an allowed IP | | `SENDING_PAUSED` | Account paused (admin OR reputation auto-pause) | Contact support / clean lists | | `SANDBOX_QUOTA_REACHED` | Daily 200/day sandbox cap hit | Request production access | | `FEATURE_LOCKED` | Plan doesn't include this feature | Upgrade plan | ## 404 Not Found | Code | Cause | Fix | |---|---|---| | `PARTNER_NOT_FOUND` | Account ID doesn't exist | Check the ID | | `IDENTITY_NOT_FOUND` | Identity hasn't been created | Create via `POST /identities` | | `CONFIG_SET_NOT_FOUND` | Configuration set name unknown | Check name spelling | | `TEMPLATE_NOT_FOUND` | Template name not registered | Create via `POST /templates` | | `MESSAGE_NOT_FOUND` | message_id doesn't match any send | Check the ID + day_bucket | ## 409 Conflict | Code | Cause | Fix | |---|---|---| | `EMAIL_ALREADY_REGISTERED` | Signup with already-used email | Use forgot-password to recover | | `IDENTITY_EXISTS` | Already verified — duplicate POST | Idempotent — existing row returned | | `CONFIG_SET_NAME_TAKEN` | Another set with that name exists | Pick a unique name | ## 429 Too Many Requests | Code | Cause | Fix | |---|---|---| | `RATE_LIMITED` | Per-second send rate exceeded | Backoff and retry | | `OTP_RATE_LIMITED` | OTP resend before cooldown | Wait 60 seconds | ## 500 Internal Server Error | Code | Cause | Fix | |---|---|---| | `DB_ERROR` | Database query failed | Retry with backoff — usually transient | | `INTERNAL_ERROR` | Catch-all | Retry once; if persistent, contact support | | `PAYMENT_GATEWAY_ERROR` | Zoho upstream returned 5xx | Retry — usually transient | ## 502 Bad Gateway | Code | Cause | Fix | |---|---|---| | `PAYMENT_GATEWAY_ERROR` | Zoho returned an error response | Wait + retry; check Zoho status | ## 503 Service Unavailable | Code | Cause | Fix | |---|---|---| | `DB_UNAVAILABLE` | Database connection issue | Retry — should clear within seconds | ## SMTP errors (in webhook payloads) When a `Bounce` event fires, the `bounce.bouncedRecipients[].diagnosticCode` field carries the SMTP diagnostic from the recipient's MX. Common ones: | Code | Meaning | |---|---| | `550 5.1.1 user unknown` | Recipient doesn't exist (hard bounce) | | `550 5.1.10 No such user` | Same — different MX wording | | `550 5.7.1 spam policy` | Receiver classified as spam (treat as complaint) | | `552 5.2.2 mailbox full` | Soft bounce — retry | | `421 4.7.0 try again later` | Greylisting / load — retry | | `554 5.7.1 sender rejected` | Sender domain blocked by recipient — list cleaning needed | ## Retry strategy Rule of thumb: - **400-class errors:** don't retry. Fix the request. - **402:** don't retry. Recharge first. - **403 + 404:** don't retry. Fix configuration first. - **429:** retry with exponential backoff (start 1s, double up to 60s). - **500 / 502 / 503:** retry up to 3 times with exponential backoff. Idempotency: `/send` is NOT idempotent on retry — duplicate calls with the same body will produce duplicate email sends. Implement your own dedup against your business identifier (charge_id, etc.) before calling `/send`. ## When to contact support - 500-class errors persist > 5 minutes - 402 even though wallet balance shows positive - 403 SENDING_PAUSED with no clear cause in `/reputation` Email support@splashifypro.in or open a ticket in Splashify Pro Email. ================================================================================ # FAQ Section: Guides › Knowledge Base URL: https://email-docs.splashifypro.com/knowledge-base/faq ================================================================================ > Common questions about the Splashify Pro Email API. # FAQ ## Account & Billing ### How long does production access take? Most requests are reviewed within 24 business hours. Clean applications (verified domain, real use case, no obvious red flags) are typically approved within an hour. ### Can I have multiple API keys? Yes — generate as many as you need from **Settings → API Keys**. Common pattern: one per environment (staging/production), one per service (web app / cron worker / etc). Revoke individually without affecting the others. ### Is there a free tier? Sandbox accounts get 200 emails/day free. After production access, you pay ₹0.03/email from email #1. There's no monthly minimum or commitment. ### How do I close my account? Email support@splashifypro.in. Wallet balance can either be transferred to a new account or refunded under exceptional circumstances. ## Sending ### Can I send from a Gmail address? No. We refuse to verify public-domain mailboxes (gmail.com, yahoo.com, outlook.com, etc.) — sending bulk through them violates the providers' TOS and would get our IP blocklisted. Use your own domain. ### Can I send to anyone? In **production**, yes. In **sandbox**, only to verified-recipient addresses (email-address identities you've explicitly added). ### What's the maximum recipients per send? 50 per `/send` request. For larger lists, use `/send-bulk` (50 destinations × 50 recipients = 500 max per request) or a campaign-style fan-out. ### What's the maximum email size? 10 MB total (HTML + text + attachments). The MIME-encoded message counts toward this limit. ### Can I attach files? Not via `/send` directly today. `/send-raw` accepts a complete MIME message (base64-encoded) — you build the multipart structure yourself. Attachment-aware send is on the roadmap. ### Are there inline images? With `/send-raw` you control the entire MIME tree, including inline `Content-ID:` references. With `/send` use externally-hosted images (e.g. on a CDN) — most modern email clients strip `cid:` references when forwarded anyway. ## Domain & Identity ### Why do I need to verify a domain? Without verification, anyone could claim to send from your domain through our infrastructure. Verification proves ownership and is required by every modern ESP for the same reason. ### How long does DNS verification take? After publishing the records, typically 5-15 minutes. Some DNS providers cache aggressively (Cloudflare flattening, GoDaddy 24-hour TTL) — call `POST /verify` after publishing and check `status`. ### Can I use a subdomain? Yes — `mail.acme.com` is a valid identity. Common pattern: - `mail.acme.com` for transactional sends - `news.acme.com` for marketing This isolates reputation between mail types. ### What if my DKIM CNAME is flattened by my DNS provider? Cloudflare's CNAME flattening serves the resolved TXT record directly. We accept either CNAME OR TXT for the DKIM check — flattened-but-correct records pass. ## Webhooks ### How fast do webhooks fire after a send? Send + Reject webhooks fire within ~1 second of the API response. Delivery webhooks fire within ~5-30 seconds (the SMTP attempt time). Bounce webhooks fire within seconds (sync hard bounces) or minutes to hours (async DSN bounces). ### What if my webhook endpoint is down? We retry on 5xx + timeout per the [retry schedule](/webhooks/retries) (1min, 5min, 15min). After ~21 minutes total we give up. 4xx responses (auth, schema mismatch) get NO retry — your URL is broken. ### Can I have multiple webhook destinations? Yes — up to 5 per configuration set. Useful for routing engagement events to one URL and deliverability events to another. ### How do I rotate the webhook secret? PATCH the destination with a new `webhook_secret`. The API never echoes the new value back, so save it locally before the next event fires. Brief overlap window is your responsibility — accept both old + new for ~30 seconds during rotation. ## Pricing ### Is the rate marketing-vs-transactional? No. Flat ₹0.03 per email regardless of category. Simpler for both sides. ### Are SMS credits separate? Yes — SMS is a separate product with its own billing. This API is email-only. ### Do I get a tax invoice? Yes. Every wallet recharge generates a Zoho Billing invoice with GST (for India-based customers with GSTIN). Downloadable from Splashify Pro Email. ## Compliance ### Is this CAN-SPAM compliant? The API supports compliance — auto-injected Unsubscribe headers (RFC 8058 one-click), suppression list, no anonymous sending. But compliance is YOUR responsibility — you must ensure recipients opted in, your unsubscribe link works, and your physical mailing address appears in the body. ### GDPR / DPDP? Same answer — we provide the tools (suppression list for erasure requests, audit logs for data subject access requests). You are the data controller; we're the processor. ### What about CASL (Canada)? Same model. Express consent + clear identification + working unsubscribe + 10-day honor window. We honor the platform-level suppression list immediately, but you must process unsubscribe clicks via webhook and update your own user state. ## Migration ### I'm coming from AWS SES — how compatible is the API? Endpoint shapes and response field names map 1:1 in most cases. The webhook event payload shape matches AWS SES SNS event publishing exactly. SDKs feel similar (resource → action). Most migrations are a base-URL swap + an auth header swap. ### From Resend / Postmark / SendGrid? Similar shapes. The biggest difference is the [configuration set + event destination model](/knowledge-base/concepts/configuration-sets) which mirrors AWS SES rather than the per-message metadata model some providers use. If you used SES configuration sets, you're home. ### Can I forward existing webhooks? We don't accept incoming webhooks (we deliver them, we don't receive). For event-source migration, set up a webhook destination on a new config set and migrate sends to use it. ## Support ### Where do I get help? - **Maya AI assistant**: every page has the ✨ button bottom-right - **Search** (Ctrl/⌘+K): every doc page is indexed - **Email support**: support@splashifypro.in - **Splashify Pro Email**: built-in support ticket flow ### Is there a status page? Yes — [status.splashifypro.com](https://status.splashifypro.com). We post incidents within ~5 minutes of detection. ### Where's the changelog? Linked from the Splashify Pro Email footer. Subscribe to the RSS feed to get notified of new endpoints + behaviour changes. ================================================================================ # Connected apps Section: Guides › Knowledge Base URL: https://email-docs.splashifypro.com/knowledge-base/connected-apps ================================================================================ > Connect other apps to your Splashify Pro Email account, see what each one can do, and remove or report an app. # Connected apps Some apps you use, like a CRM or a shop builder, can connect to your Splashify Pro Email account and send email or read reports for you. A connected app can do only what you allowed. You can see every connected app and remove any of them at any time. ## Connect an app You start in the other app, usually with a button like **Connect Splashify Pro**. It opens a page on email.splashifypro.com that shows: - the app's name and logo, and who made it. A **verified** app has a green **Verified** badge and the company that made it; any other app shows **by an unverified developer** and a notice that we have not checked it; - the Splashify Pro Email account it will connect to; - what the app will be able to do, in plain words; - how its emails are charged; - where you go back to after you allow. Click **Allow** to connect, or **Cancel**. You go back to the other app either way: after **Allow** you first see **Connected**, and if the page does not take you back by itself, click **Continue**. ### Who can connect apps Only you, signed in to the panel, can connect or remove apps. An API key cannot, and neither can our support team when they look at your account. ### What it costs Every email a connected app sends is charged like the emails you send yourself: from your wallet at your normal rates, or to your account for postpaid accounts. An app that is not verified can send up to **500 emails a day** from your account and cannot use bulk sending. After you allow an app, we email you which app was connected and what it can do. If you did not connect it, remove it at once. ### Allowed IPs If your account only accepts API calls from its [allowed IP addresses](https://email.splashifypro.com/allowed-ips), a connected app's requests are refused unless they come from one of them. The connect page shows the addresses the app says it uses; add them in **Allowed IPs**. ## See your connected apps Open **Settings** and click **Connected apps**. For each app you see what it can do, when and by whom it was connected, and when it was last used. Connecting and removing apps also show in your **Activity logs**. ## Remove an app Click **Remove** on the app's row, then **Remove** again to confirm. The app loses access at once. Anything it already sent stays in your account. ## Report an app If an app does something you did not expect, click **Report** on the app's row, tell us what went wrong and click **Send report**. We look into every report. Remove the app too if you do not want it to keep working. ## Build your own app Developers build apps at [dev.splashifypro.com](https://dev.splashifypro.com). See [Connected apps (OAuth)](/api-reference/connected-apps). ================================================================================ # Concepts Section: Guides › Knowledge Base: Concepts URL: https://email-docs.splashifypro.com/knowledge-base/concepts ================================================================================ > The mental model behind the Splashify Pro Email API. # Concepts A short tour of the primitives the API exposes. If you've worked with AWS SES the names map 1:1 — sending identities, configuration sets, suppression lists, all here. ## The 5 primitives ``` ┌─────────────────────────────────────────────────────────┐ │ Your Splashify Pro account │ │ │ │ ┌───────────────┐ ┌───────────────┐ ┌─────────────┐ │ │ │ Identity │ │ Identity │ │ Identity │ │ │ │ (your domain) │ │ (alt addr) │ │ (3rd domain)│ │ │ └───────┬───────┘ └───────┬───────┘ └──────┬──────┘ │ │ │ verified │ verified │ pending │ │ ┌───────┴──────────────────┴─────────────────┴──────┐ │ │ │ Configuration Sets │ │ │ │ ┌──────────────┐ ┌──────────────┐ │ │ │ │ │ "production" │ │ "marketing" │ │ │ │ │ │ ↓ events │ │ ↓ events │ │ │ │ │ │ → webhook A │ │ → webhook B │ │ │ │ │ │ → webhook B │ │ │ │ │ │ │ └──────────────┘ └──────────────┘ │ │ │ └────────────────────────────────────────────────────┘ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ Suppression list (account-wide) │ │ │ │ bounced@example.com angry@example.com ... │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ Wallet: ₹X.XX Sandbox: ON / OFF │ └─────────────────────────────────────────────────────────┘ ``` 1. **[Sending identities](/knowledge-base/concepts/sending-identities)** — verified domains + email addresses you can send `From:`. 2. **[Configuration sets](/knowledge-base/concepts/configuration-sets)** — logical groupings of sends that route events to webhook destinations. 3. **[Suppression list](/knowledge-base/concepts/suppression)** — account-wide blocklist. Auto-populated by hard bounces + complaints + unsubscribes. 4. **[Reputation](/knowledge-base/concepts/reputation)** — your account's bounce + complaint rate. Drives auto-pausing if thresholds breach. 5. **[Sandbox vs production](/knowledge-base/concepts/sandbox)** — sandbox = 200/day cap + verified-only recipients. Production = real volume after a quick review. ## Hierarchy - **Identity** is account-wide. Verifying `acme.com` lets you send from any address at `acme.com`. - **Configuration set** scopes sends — events from sends inside a config set go to that set's webhook destinations. - **Suppression list** is account-wide by default. Each config set can opt to also suppress per-config-set on bounces / complaints via `suppression_options`. ## Send-time flow ``` POST /send (with config_set + from + to) │ ▼ 1. From-domain on a verified identity? ──── no → 400 FROM_NOT_VERIFIED │ yes ▼ 2. Recipient on suppression list? ──── yes → status=rejected │ no ▼ 3. Wallet balance >= ₹0.03? ──── no → 402 INSUFFICIENT_BALANCE │ yes (or in sandbox free tier) ▼ 4. Daily quota not exceeded? ──── no → 429 SANDBOX_QUOTA_REACHED │ yes ▼ 5. Queue the email for delivery │ ▼ 6. Fire "Send" event → webhook destinations │ ▼ 7. SMTP attempt → recipient MX ├── 250 OK → "Delivery" event ├── 5xx hard bounce → "Bounce" event + suppress └── 4xx soft bounce → retry (5min, 30min, 2h) ``` ================================================================================ # Sending Identities Section: Guides › Knowledge Base: Concepts URL: https://email-docs.splashifypro.com/knowledge-base/concepts/sending-identities ================================================================================ > Verified domains and email addresses are the foundation of every send. # Sending Identities A **sending identity** is anything you've proven you control: - A **domain** (preferred: covers any address at that domain), or - A specific **email address** (limited to that one mailbox) Every email you send must have a `From:` address that matches a **verified** identity. Sending from an unverified address returns `400 FROM_NOT_VERIFIED`. ## Why verification? Without verification, anyone could claim to send from `security@yourbank.com` through our infrastructure. Verification proves you control the domain or address at the DNS / mailbox level. This is the same reason AWS SES, SendGrid, Postmark, Mailgun, and every other ESP requires it. It's not optional in 2026's email landscape. ## Domain verification A domain is verified with DNS records you publish: SPF, DKIM and DMARC, and for most domains also DKIM 2 and Return path. Once SPF, DKIM and DMARC are published and checked, you can send from **any address** at the domain: `hello@`, `alerts@`, `noreply@`, etc. Create the identity: ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"identity_type": "DOMAIN", "identity_value": "yourcompany.com"}' ``` The response lists the records to publish under `dns_records`: | Key | Record | Type | Hostname | Value | |---|---|---|---|---| | `spf` | SPF | TXT | `yourcompany.com` | `v=spf1 include:_spf.mail.splashifypro.com ~all` | | `dkim` | DKIM | CNAME | `splashify._domainkey.yourcompany.com` | `splashify._domainkey.mail.splashifypro.com` | | `dmarc` | DMARC | TXT | `_dmarc.yourcompany.com` | `v=DMARC1; p=quarantine; rua=mailto:dmarc@splashifypro.com` | | `dkim2` | DKIM 2 | TXT | made for your domain | made for your domain | | `return_path` | Return path | CNAME | made for your domain | made for your domain | What the last two do: - **DKIM 2** is a second DKIM key. It lets inbox providers verify mail from your domain on all our sending servers. - **Return path** lets bounced mail come back to us so your domain keeps a clean sending record. Add all five. You can send as soon as the first three are verified; add the other two for the best delivery. The identity `status` does not wait for them. If a domain lists only `spf`, `dkim` and `dmarc`, publish those three. Each entry of `dns_records` has the same shape: ```json { "dns_records": { "spf": { "type": "TXT", "hostname": "yourcompany.com", "value": "v=spf1 include:_spf.mail.splashifypro.com ~all", "pass": false }, "dkim": { "type": "CNAME", "hostname": "splashify._domainkey.yourcompany.com", "value": "splashify._domainkey.mail.splashifypro.com", "pass": false }, "dmarc": { "type": "TXT", "hostname": "_dmarc.yourcompany.com", "value": "v=DMARC1; p=quarantine; rua=mailto:dmarc@splashifypro.com", "pass": false }, "dkim2": { "type": "TXT", "hostname": "...", "value": "...", "pass": false }, "return_path": { "type": "CNAME", "hostname": "...", "value": "...", "pass": false } }, "dkim2_ok": false, "return_path_ok": false } ``` When `dkim2` and `return_path` are listed, the identity also carries `dkim2_ok` and `return_path_ok` next to `spf_ok`, `dkim_ok` and `dmarc_ok`. They can show up a moment after you create the identity: if the create response lists only three records, read the identity again with `GET /partner/email/identities` or open the **Sending Identities** page in Splashify Pro Email. Always copy the hostname and value of `dkim2` and `return_path` from there; they are made for your domain. After publishing on your DNS provider, trigger a re-check: ```bash curl -X POST https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com/verify \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` The same call re-checks all the records. Once `"status": "VERIFIED"` lands, you're good. When `dkim2_ok` or `return_path_ok` in that response is still `false`, that record is pending: add it for the best delivery. We re-check verified domains every 24 hours; if the SPF, DKIM or DMARC record disappears, status flips back to `PENDING` and we email you. ## Email-address verification For low-volume use cases or when you can't add DNS records (you're using a public-domain mailbox like Gmail), verify a single address: ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"identity_type": "EMAIL_ADDRESS", "identity_value": "alerts@yourcompany.com"}' ``` We email a verification link to the address. Click it (or use the verify endpoint directly with the included token) and the address becomes verified. > **Public-domain caveat:** We refuse to verify addresses at common > public providers (`gmail.com`, `yahoo.com`, `outlook.com`, etc.). > Sending bulk through `you@gmail.com` violates Google's TOS and > would get our IP blocklisted within hours. Use your own domain. ## Display name vs verified address You can set a friendly display name without verifying it: ```json { "from": "Sarah from Acme " } ``` `acme.com` must be verified. `Sarah from Acme` is unverified: recipients see whatever string you supply. ## Multiple domains Verify as many domains as you like. Common pattern: one for transactional (`mail.acme.com`), one for marketing (`news.acme.com`). Helps deliverability: bounces / complaints on the marketing domain don't drag down transactional reputation. ## Listing your identities ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Removing an identity ```bash curl -X DELETE https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` In-flight sends from that domain complete normally; new sends are rejected with `FROM_NOT_VERIFIED`. ## Auto-recheck behaviour Verified domains: re-checked every 24 hours. Pending domains: re-checked every 1 hour for 7 days, then drop to `FAILED` if SPF, DKIM and DMARC still aren't published. You can always re-trigger via `POST /verify`. ## Read more - [SPF / DKIM / DMARC explainer](/knowledge-base/deliverability/spf-dkim-dmarc) - [API reference: identities](/api-reference/identities/create) ================================================================================ # Configuration Sets Section: Guides › Knowledge Base: Concepts URL: https://email-docs.splashifypro.com/knowledge-base/concepts/configuration-sets ================================================================================ > Logical groupings of sends — control event routing, suppression scope, and attribution. # Configuration Sets A **configuration set** is a logical bundle of sends that share event-destination wiring + suppression behaviour. Modelled directly on AWS SES configuration sets. If you're shipping email for a single product, you might never create a config set — defaults work fine. But the moment you have: - **Multiple downstream tenants** (one for each customer) - **Multiple email types** (transactional vs marketing) - **Distinct webhook destinations** per use case ...config sets become essential. ## What a config set carries | Field | Purpose | |---|---| | `name` | Human-friendly identifier you reference on `/send` | | `description` | Free-text notes | | `customer_id` | Optional. Your downstream end-customer attribution | | `sending_enabled` | Kill switch — disable sends through this set without deleting it | | `reputation_tracking_enabled` | Whether bounces/complaints from this set count toward your reputation rolling window | | `suppression_options` | Which categories auto-add to suppression list: `NONE` / `BOUNCE` / `COMPLAINT` / `BOUNCE_AND_COMPLAINT` | | `tags` | Arbitrary key-value pairs that ship in the webhook `mail.tags` field | ## Create one ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "production", "description": "Production transactional sends", "suppression_options": "BOUNCE_AND_COMPLAINT", "reputation_tracking_enabled": true, "tags": { "env": "prod", "team": "platform" } }' ``` ## Reference on send ```json { "from": "alerts@yourcompany.com", "to": ["customer@example.com"], "subject": "Payment received", "html_body": "...", "configuration_set_name": "production" } ``` Events from this send fan out to every event destination attached to the `production` config set. ## Multi-tenant pattern If you're running a SaaS that sends email on behalf of customers, create one config set per customer: ```js // On customer signup: const cfg = await client.configurationSets.create({ name: `customer_${customer.id}`, customer_id: customer.id, description: `Email sends for ${customer.name}`, tags: { customer_id: customer.id, plan: customer.plan }, }); // On send: await client.emails.send({ from: customer.fromAddress, to: [recipient], configuration_set_name: `customer_${customer.id}`, ... }); ``` Now per-customer stats roll up cleanly via: ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/stats?config_set_id=...' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` And per-customer event destinations let each customer have their own webhook URL. ## Event destinations A config set without event destinations still records events internally — they show up in `GET /events` and `GET /stats` — but nothing fans out to your servers. Add a webhook destination: ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets/$CFG/event-destinations \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "production-webhook", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/email", "webhook_secret": "...", "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"] }' ``` Multiple destinations per set are fine — useful for routing engagement events to one URL and deliverability events to another. ## Disabling a config set ```bash curl -X PATCH https://api.splashifypro.com/api/v1/partner/email/configuration-sets/$CFG \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -d '{"sending_enabled": false}' ``` Sends with `configuration_set_name` matching this set get `status: rejected` until re-enabled. In-flight sends complete. ## Suppression options | Value | Behaviour | |---|---| | `NONE` | Auto-suppression OFF for this set's sends | | `BOUNCE` | Hard bounces auto-add to suppression list | | `COMPLAINT` | Complaints auto-add to suppression list | | `BOUNCE_AND_COMPLAINT` | Both auto-add (default + recommended) | Manual suppressions via `PUT /suppression/:email` always go to the account-wide list regardless of config-set settings. ## Reputation tracking When `reputation_tracking_enabled: false`, bounces + complaints from this set's sends are excluded from your account's rolling reputation calculation. Useful for: - Test campaigns where you knowingly send to low-quality addresses - Risk-isolated experiments Defaults to `true`. Don't turn this off unless you really mean it. ## Limits - 100 configuration sets per account - 5 event destinations per configuration set - Names are unique per account, case-sensitive, alphanumeric + `_` + `-`, 1-256 chars ================================================================================ # Suppression List Section: Guides › Knowledge Base: Concepts URL: https://email-docs.splashifypro.com/knowledge-base/concepts/suppression ================================================================================ > Account-wide blocklist that protects your sender reputation. # Suppression List The suppression list is your account's blocklist of recipient addresses we won't send to. It exists to protect: - **Your reputation** — repeated bounces / complaints tank your bounce + complaint rate, which mailbox providers use as a primary signal. - **The recipient** — opting out, manually unsubscribing, or marking as spam should mean they never hear from you again. - **The platform** — collectively low bounce/complaint rates keep the platform's deliverability healthy across all senders. ## What gets auto-added | Trigger | Reason | |---|---| | Hard bounce | Permanent delivery failure (no such user, mailbox terminated, etc.) | | Complaint | Recipient marked the email as spam (FBL report from inbox provider) | | Unsubscribe | Recipient clicked a one-click unsubscribe (RFC 8058) link | Soft bounces (mailbox full, server temporarily unavailable, etc.) do NOT auto-suppress — we retry up to 3 times, then mark the row failed without suppressing. ## What we DON'T auto-add - Single soft bounces (we retry first) - API rejections (e.g. invalid recipient format) — those don't reach SMTP - Greylist 4xx responses (we retry per-domain backoff) ## Behaviour at send time When you call `/send`, every recipient is checked against the suppression list **before** any SMTP attempt. Recipients on the list: - Get `status: rejected` in the per-recipient response - Don't burn wallet balance — you're not billed for rejected recipients - Generate a `Reject` webhook event with `reason: "suppressed"` This matters at scale — sending a bulk to a list with 5% suppressed addresses saves you 5% of the wallet hit + keeps your bounce rate clean. ## Listing the suppression list ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/suppression?reason=BOUNCE&limit=100' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Filters: `reason` (BOUNCE / COMPLAINT / UNSUBSCRIBE / MANUAL), `search` (substring), `limit` (1-1000). ## Adding manually ```bash curl -X PUT https://api.splashifypro.com/api/v1/partner/email/suppression/legal-hold@example.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason": "MANUAL", "details": "GDPR erasure request 2026-05-03"}' ``` Use cases: - GDPR / DPDP erasure requests - Customer-side opt-outs that didn't come through your unsubscribe flow - Known-bad addresses you want to skip preemptively ## Removing ```bash curl -X DELETE https://api.splashifypro.com/api/v1/partner/email/suppression/customer@example.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Removal lets you re-send to that address. Be conservative — if the address bounced hard or complained, removing it and re-sending is likely to get you suppressed again + drag your reputation down. ## Per-config-set suppression scope By default, suppressions are account-wide. Each config set can override which categories auto-suppress via the `suppression_options` field: | Value | What gets auto-suppressed | |---|---| | `NONE` | Nothing (rare — you're saying "send everything regardless") | | `BOUNCE` | Hard bounces only | | `COMPLAINT` | Complaints only | | `BOUNCE_AND_COMPLAINT` | Both (recommended default) | The check at send time still hits the account-wide list — config- set settings only affect what's auto-WRITTEN to the list. ## Best practices - **Don't programmatically remove suppressions in bulk.** Each removed entry that re-bounces hurts you twice. - **Sync to your application's user table.** Listen to `Bounce` + `Complaint` webhooks, mark those users `email_unsubscribed: true` in your DB, and skip them in your own outbound logic. Defense in depth. - **Honor unsubscribe requests instantly.** If a customer clicks unsubscribe in your app's preferences page, push their email to our suppression list via PUT — don't wait for the next campaign to filter them. - **Audit periodically.** Run `GET /suppression?reason=BOUNCE` once a month and cross-reference against your active customer list — bounced addresses on your billing roster mean broken support delivery + missed renewal emails. ================================================================================ # Reputation Section: Guides › Knowledge Base: Concepts URL: https://email-docs.splashifypro.com/knowledge-base/concepts/reputation ================================================================================ > How we track sender reputation + what triggers auto-pause. # Reputation Mailbox providers (Gmail, Outlook, Yahoo, Apple Mail) decide whether to deliver your mail to inbox, junk, or refuse it entirely based on **sender reputation** — a continuously-updated score derived from your bounce rate, complaint rate, content patterns, and recipient engagement. We track two of the load-bearing signals: - **Bounce rate** — `bounced / sent` over the rolling 14-day window - **Complaint rate** — `complained / sent` over the rolling 14-day window Both are computed from the per-day counter table behind `GET /partner/email/stats`. ## Status thresholds ``` bounce > 10% OR complaint > 0.5% → PAUSED (auto-pause) bounce > 5% OR complaint > 0.1% → AT_RISK (warning) else → HEALTHY ``` These match AWS SES and the broader industry-standard "watch-list" thresholds. ## What happens at each threshold ### `HEALTHY` Default state. No special handling. ### `AT_RISK` - Email notification to the account contact - Banner on the Splashify Pro Email dashboard - Recommendation to investigate recent campaigns + clean lists - No automatic action against your sending — but you should fix the underlying issue immediately ### `PAUSED` - All `/send` calls return `403 SENDING_PAUSED` - The reputation status reflects on `GET /partner/email/quotas` - Your panel dashboard shows the alert + reason - An admin reviews + decides whether to: - Drop you back to sandbox (so you can test fixes) - Re-enable with a stern warning - Keep paused pending list-cleaning evidence To resume sending after PAUSED: 1. Identify the breach source (which campaigns / list segments caused it) 2. Clean the list — remove every address that bounced / complained 3. Reach out to support with your remediation plan 4. Our team reviews it and lifts the pause on your account ## What we don't track (yet) - **Engagement signals** (open rate, reply rate, forward rate) — on roadmap for shared-IP reputation; today these only matter for dedicated-IP customers. - **Spam-filter scores** (SpamAssassin etc.) — you control content; our infrastructure handles authentication. - **Domain age / DMARC alignment** — hardened automatically through the verification flow. ## Per-config-set vs account-wide By default reputation is computed at the **account level**. Sends across all config sets contribute to the same rolling window. If you want to isolate a high-risk experiment from your main reputation, set `reputation_tracking_enabled: false` on that config set. Bounces + complaints from those sends are still recorded in your event log + suppression list, but excluded from the rolling reputation calculation. Use sparingly — `false` is an opt-out from a healthy default. ## Inspecting your reputation ```bash curl https://api.splashifypro.com/api/v1/partner/email/reputation \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Response: ```json { "success": true, "window_days": 14, "sent": 12500, "bounced": 218, "complained": 4, "bounce_rate": 0.01744, "complaint_rate": 0.00032, "status": "HEALTHY" } ``` `/quotas` returns the same status alongside daily-quota info — use that endpoint as the single read-once-per-page source on your dashboard. ## How to keep reputation healthy 1. **Send to opt-in lists only.** Buying lists or scraping email addresses is the #1 cause of complaint-rate breaches. 2. **Honor unsubscribes within 10 days.** It's a CAN-SPAM / CASL / DPDP requirement AND it's how you avoid complaint spikes. 3. **Verify before sending.** Hitting hundreds of stale addresses once spikes your bounce rate hard. 4. **Warm up new identities slowly.** Mailbox providers throttle first-contact volume — start with low volume to high-engagement recipients, ramp over a week or two. 5. **Watch your DMARC reports.** Misaligned mail (sent through us but with wrong From-domain) gets quarantined or rejected — that shows up as bounces in our stats. ================================================================================ # Sandbox vs Production Section: Guides › Knowledge Base: Concepts URL: https://email-docs.splashifypro.com/knowledge-base/concepts/sandbox ================================================================================ > What sandbox mode means, why we ship every account in it by default, and how to leave. # Sandbox vs Production Every new account starts in **sandbox mode**. Sandbox is a deliberately constrained version of production where: | Limit | Sandbox | Production (default) | |---|---|---| | Daily send quota | **200 emails/day** | 50,000 emails/day | | Peak send rate | **1 email/second** | 14 emails/second | | Recipient restrictions | Verified-recipient addresses only (TODO; today: cap-only) | Anyone | | Per-email price | First 200/day **free** | ₹0.03/email from email #1 | | All other features | Identical to production | — | Sandbox is NOT a free trial. It's a probation period — we want to see you can verify a domain, configure webhooks, and send a few test emails without making the platform's shared IP reputation worse. ## Why we ship sandbox by default In our first year of operation, ~30% of new accounts caused some form of deliverability damage in week 1. Reasons: - Buying / scraping lists - Testing in production with bogus recipients - Misconfigured templates that 100% bounced Sandbox protects everyone. Once you've shown a clean signal — even just a handful of successful sends + a verified domain — production access is fast. ## What still works in sandbox Everything at the API level. You can: - Verify domain identities + email-address identities - Create configuration sets + event destinations + templates - Send up to 200/day to whoever - Receive webhooks normally - Add suppression entries + check stats + check reputation The constraints are **velocity-only** — daily quota + rate limit. The functional surface is identical. ## Requesting production access ```bash curl https://api.splashifypro.com/api/v1/partner/email/production-access \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "use_case": "We send transactional emails for our SaaS app — signup confirmation, password reset, payment receipts, weekly digest. ~5000 emails/day across all customers.", "email_volume_estimate": "5000-15000 per day", "has_unsubscribe_method": true, "has_consent_proof": true }' ``` Required fields: | Field | What we want | |---|---| | `use_case` | A real description (≥30 chars). Says WHO you're sending to + WHY they signed up | | `email_volume_estimate` | Realistic daily volume. Don't overstate; quotas can be raised later | | `has_unsubscribe_method` | Confirm you have an unsubscribe link in marketing emails | | `has_consent_proof` | Confirm recipients opted in (signup, double-opt-in, purchase, etc.) | All four must be present. Faking them violates our AUP — we audit periodically + downgrade accounts that lied. ## Review timeline Most requests are reviewed within **24 business hours**. If your request: - Has a clear use case + verified domain + zero suppression-list entries → typically approved within an hour - Has a vague use case OR no verified domain yet → comes back with questions - Looks like list-buying / cold outreach → denied with reason You can resubmit any number of times after a denial — fix the flagged issue + try again. ## What approval changes ``` sandbox: true → sandbox: false daily_send_quota: 200 → 50,000 peak_send_rate_per_second: 1 → 14 ``` These are baseline production numbers. For higher volume reach out to support. Caps can be raised per account. ## Inspecting your status ```bash curl https://api.splashifypro.com/api/v1/partner/email/quotas \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Returns: ```json { "daily_send_quota": 200, "peak_send_rate_per_second": 1, "sandbox": true, "sent_today": 47, "sandbox_free_used_today": 47, "reputation_status": "HEALTHY", ... } ``` ## Common denial reasons - **No use case description.** Empty + 1-line submissions are declined unread. - **No verified domain.** We require at least one domain identity in `VERIFIED` status before approving. Sandbox is a 5-minute exercise — verify one + resubmit. - **Vague description.** "Sending email to our users" isn't enough. Tell us WHAT kind of email + HOW recipients opted in. - **Unsubscribe gap.** Marketing email without an unsubscribe link is illegal under CAN-SPAM, CASL, DPDP. Fix it before requesting. - **Cold-list pattern.** "We bought a list of 100K emails" is a decline. ================================================================================ # API Reference Section: API Reference › API Reference URL: https://email-docs.splashifypro.com/api-reference ================================================================================ > Every endpoint of the Splashify Pro Email API. # API Reference The Splashify Pro Email API is RESTful, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes + verbs. ## Base URL ``` https://api.splashifypro.com/api/v1/partner/email ``` All endpoints documented in this reference are relative to this base URL. ## Authentication Bearer token in the `Authorization` header: ```http Authorization: Bearer pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` See [Authentication](/getting-started/authentication) for key generation, rotation, and rate-limit details. ## Request format POST + PATCH + PUT bodies are JSON. Set `Content-Type: application/json`. Field names are `snake_case`. Required fields raise `400 INVALID_REQUEST` when missing. ## Response format Every response is JSON. Successful responses include `success: true`: ```json { "success": true, "data": { ... } } ``` Errors include a stable `error` code + a human-readable `message`: ```json { "success": false, "error": "FROM_NOT_VERIFIED", "message": "From address is not on a verified identity." } ``` See [Errors](/api-reference/errors) for the full list. ## Resources | Resource | Endpoints | |---|---| | **[Emails](/api-reference/emails/send)** | `/send`, `/send-raw`, `/send-template`, `/send-bulk`, `/emails/:id` | | **[Templates](/api-reference/templates/list)** | CRUD + preview | | **[Identities](/api-reference/identities/list)** | List, create, get, verify, delete | | **[Configuration Sets](/api-reference/configuration-sets/list)** | CRUD + multi-tenant attribution | | **[Event Destinations](/api-reference/event-destinations/list)** | Webhook destinations attached to config sets | | **[Suppression](/api-reference/suppression/list)** | List, get, put, delete | | **[Quotas & Stats](/api-reference/quotas/get-quota)** | Send quota, statistics, reputation, events | | **[Production Access](/api-reference/production-access/submit)** | Sandbox → production lifecycle | ## Versioning The API is versioned in the URL — `/api/v1/`. We will not introduce breaking changes within a version. New optional fields, new endpoints, and new event types may land at any time. If we ever ship `/api/v2/`, we'll keep `/api/v1/` operational for at least 12 months and announce the deprecation timeline at least 90 days in advance. ## Idempotency Send endpoints are NOT idempotent — duplicate calls produce duplicate sends. Implement application-level dedup against your business identifier (charge_id, signup_id, etc.) before calling `/send`. Idempotency-key support via `Idempotency-Key` header is on the roadmap. ================================================================================ # Pagination Section: API Reference › API Reference URL: https://email-docs.splashifypro.com/api-reference/pagination ================================================================================ > How list endpoints paginate. # Pagination List endpoints use cursor-based pagination via `limit` + `next_cursor` query parameters. ## Request ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/identities?limit=50' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` | Parameter | Type | Default | Notes | |---|---|---|---| | `limit` | int | 100 | Max 1000 | | `next_cursor` | string | — | Opaque cursor from a previous response | ## Response ```json { "success": true, "identities": [...], "count": 50, "next_cursor": "eyJpZCI6IjEyMzQ1IiwiX3QiOjE3..." } ``` `next_cursor` is opaque — do not parse it. Pass it back verbatim to fetch the next page: ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/identities?limit=50&next_cursor=eyJ...' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` When `next_cursor` is absent or empty, you've reached the end. ## Endpoints that paginate - `GET /identities` - `GET /configuration-sets` - `GET /templates` - `GET /suppression` - `GET /events` - `GET /production-access` ## Endpoints that don't - `GET /quotas`, `/stats`, `/reputation` — fixed-size responses - `GET /emails/:message_id` — single-row reads ## Default ordering Most list endpoints return newest-first. For deterministic ordering across pages, results are stable — re-fetching with the same cursor returns the same rows. ================================================================================ # Errors Section: API Reference › API Reference URL: https://email-docs.splashifypro.com/api-reference/errors ================================================================================ > API error response shape, status codes, and stable error codes. # API Errors Every error response from the Email API has the same shape: ```json { "success": false, "error": "INSUFFICIENT_BALANCE", "message": "Wallet balance ₹0.00. Recharge to continue sending." } ``` | Field | Meaning | |---|---| | `success` | Always `false` for errors | | `error` | Stable code — build retry/handling logic against this | | `message` | Human-readable text. May change for clarity over time | | `field` | (When relevant) Specific field that caused the error | For the complete error code reference + retry guidance, see [Knowledge Base → Errors](/knowledge-base/errors). ## HTTP status codes | Code | Meaning | |---|---| | `200` | Success | | `201` | Resource created | | `400` | Bad request — fix your inputs | | `401` | Missing / invalid API key | | `402` | Insufficient wallet balance — recharge | | `403` | Sandbox cap, sending paused, or feature locked | | `404` | Resource not found | | `409` | Conflict (duplicate name, etc.) | | `429` | Rate limit hit — back off | | `500` | Server error — retry with backoff | | `502` | Upstream gateway error (Zoho etc.) | | `503` | Database / dependency unavailable | ## Retry strategy | Status | Retry? | |---|---| | 4xx (except 408 / 429) | No — fix the request | | 408 / 429 | Yes — exponential backoff | | 5xx | Yes — up to 3 attempts with backoff | See [Knowledge Base → Errors](/knowledge-base/errors) for per-code guidance. ================================================================================ # Connected apps (OAuth) Section: API Reference › API Reference URL: https://email-docs.splashifypro.com/api-reference/connected-apps ================================================================================ > Let Splashify Pro Email customers connect their account to your app with OAuth 2.0, and call the Email API for them. # Connected apps (OAuth) If you build an app that many Splashify Pro Email customers use, do not ask each of them for an API key. Add a **Connect Splashify Pro** button instead: the customer signs in, sees what your app asks for and clicks Allow, and your server gets a token limited to what they allowed. This is standard OAuth 2.0 with the authorization code flow and PKCE. The full guide, with every parameter, error and limit, is on [docs.splashifypro.com](https://docs.splashifypro.com/connect-splashify-pro). This page has what is specific to Email apps. ## Get a Client ID Create a free developer account at [dev.splashifypro.com](https://dev.splashifypro.com/signup). It is separate from your Splashify Pro Email account, and you do not need to be a customer. Click **New app**, pick **Email (email.splashifypro.com)**, add your redirect URL and permissions, and copy the client secret: we show it once. ## URLs | | | |---|---| | Authorize | `https://email.splashifypro.com/oauth/authorize` | | Token | `https://api.splashifypro.com/api/v1/oauth/token` | | Revoke | `https://api.splashifypro.com/api/v1/oauth/revoke` | | API base | `https://api.splashifypro.com` | ## Permissions | Permission | What it opens | |---|---| | `account:read` | `GET /api/v1/oauth/me`. Always included. | | `email.messages:send` | `POST /api/v1/partner/email/send`, `POST /api/v1/partner/email/send-template`, `POST /api/v1/partner/email/send-bulk` (verified apps only), `GET /api/v1/partner/email/identities` | | `email.templates:read` | `GET /api/v1/partner/email/templates`, `GET /api/v1/partner/email/templates/:id`, `GET /api/v1/partner/email/templates/by-name/:name` | | `email.reports:read` | `GET /api/v1/partner/email/emails/:message_id`, `GET /api/v1/partner/email/stats`, `GET /api/v1/partner/email/quotas`, `GET /api/v1/partner/email/events`, [`GET /api/v1/partner/email/bounce-report`](/api-reference/bounce-report) | | `email.contacts:write` | [`GET .../audiences`](/api-reference/audiences/list), [`GET .../audiences/:id`](/api-reference/audiences/get), [`POST .../audiences/:id/contacts`](/api-reference/audiences/add-contacts), [`PATCH .../audiences/:id/contacts/:email`](/api-reference/audiences/update-contact) | | `email.contacts:read` | [`GET .../audiences`](/api-reference/audiences/list), [`GET .../audiences/:id`](/api-reference/audiences/get), [`GET .../audiences/:id/contacts`](/api-reference/audiences/list-contacts). Verified apps only. | Every other route, including `send-raw`, the IP allowlist, account deletion and CSV exports, is refused with `403 endpoint_not_allowed`. ## The flow ```bash # 1. Send the customer here https://email.splashifypro.com/oauth/authorize?response_type=code&client_id=spo_app_XXXX&redirect_uri=https%3A%2F%2Fyourapp.example%2Fsplashify%2Fcallback&scope=email.messages%3Asend%20email.reports%3Aread&state=RANDOM_STATE&code_challenge=CHALLENGE&code_challenge_method=S256 # 2. Swap the code for tokens (server side) curl -X POST https://api.splashifypro.com/api/v1/oauth/token \ -u "spo_app_XXXX:spo_cs_YYYY" \ -d grant_type=authorization_code \ -d code=spo_ac_ZZZZ \ -d redirect_uri=https://yourapp.example/splashify/callback \ -d code_verifier=VERIFIER # 3. Send an email for the customer curl -X POST https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer spo_at_AAAA" -H "Content-Type: application/json" \ -d '{"from":"orders@customer-domain.example","to":["asha@example.com"],"subject":"Your order","html_body":"

On its way.

"}' # 4. Refresh (save the new refresh_token every time) curl -X POST https://api.splashifypro.com/api/v1/oauth/token \ -u "spo_app_XXXX:spo_cs_YYYY" -d grant_type=refresh_token -d refresh_token=spo_rt_BBBB ``` Access tokens last 1 hour. Refresh tokens rotate on every use: always save the new one. ## Good to know - Send the token only as `Authorization: Bearer spo_at_...`. - Emails your app sends are charged to the customer's wallet, or to their account when it is postpaid, at their normal rates. - Until your app is verified it can connect up to 25 accounts, send up to 500 emails a day per account, send each email to one address (`to`, `cc` and `bcc` together), and cannot use `send-bulk`. - If the customer's account has allowed IP addresses, your calls must come from one of them, and IPv6 addresses are refused. List your server IPs on your app so customers can add them. - Errors from the token gate use the Email API shape: `{"error": "insufficient_scope", "message": "This app was not allowed to do this."}`. - There are no webhooks to apps yet. Poll [Get email status](/api-reference/emails/get-status) for delivery. Read the full guide: [Connect with Splashify Pro](https://docs.splashifypro.com/connect-splashify-pro). ================================================================================ # Send email Section: API Reference › Emails URL: https://email-docs.splashifypro.com/api-reference/emails/send ================================================================================ > POST /api/v1/partner/email/send — send a transactional or marketing email. # Send email Send an email to one or more recipients. Equivalent to AWS SES `SendEmail`. ```http POST /api/v1/partner/email/send ``` > **Try it on the web page:** `POST /api/v1/partner/email/send` Send an email to one or more recipients. ## Request body | Field | Type | Required | Notes | |---|---|---|---| | `from` | string | yes | Sender address. Must be on a verified [identity](/api-reference/identities/create). Format: `"name "` or just `addr@example.com` | | `to` | string[] | yes | Up to 50 recipients (combined `to` + `cc` + `bcc`) | | `cc` | string[] | no | Carbon copy | | `bcc` | string[] | no | Blind carbon copy | | `reply_to` | string | no | Sets the `Reply-To:` header | | `subject` | string | yes | Subject line | | `html_body` | string | conditional | HTML body. One of `html_body` or `text_body` is required | | `text_body` | string | conditional | Plaintext body. Auto-derived from HTML if omitted | | `configuration_set_name` | string | no | Routes events to this config set's destinations | | `customer_id` | string (uuid) | no | Optional downstream customer attribution on your side | | `category` | string | no | `transactional` (default) or `marketing` | | `tags` | object | no | Arbitrary key-value pairs that ride on `mail.tags` in webhooks | ## Response ```json { "success": true, "results": [ { "recipient": "customer@example.com", "message_id": "550e8400-e29b-41d4-a716-446655440000", "status": "queued" } ] } ``` `results` carries one entry per recipient — `to` + `cc` + `bcc` are flattened. | Field | Notes | |---|---| | `recipient` | Lowercase + trimmed | | `message_id` | Use this on `GET /emails/:message_id` to poll status | | `status` | `queued` or `rejected` | | `reason` | Present when `status: rejected` — typically `"suppressed"` | ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome", "html_body": "

Welcome

", "text_body": "Welcome." }' ``` ## Node ```js const res = await fetch( "https://api.splashifypro.com/api/v1/partner/email/send", { method: "POST", headers: { Authorization: `Bearer ${process.env.SPLASHIFY_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "hello@yourcompany.com", to: ["customer@example.com"], subject: "Welcome", html_body: "

Welcome

", }), } ); const data = await res.json(); ``` ## Python ```python import requests, os r = requests.post( "https://api.splashifypro.com/api/v1/partner/email/send", headers={"Authorization": f"Bearer {os.environ['SPLASHIFY_API_KEY']}"}, json={ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome", "html_body": "

Welcome

", }, ) ``` ## Attachments `/send` accepts an `attachments[]` array of base64-encoded files. PDFs, images, documents, spreadsheets, ZIPs are all supported. ```json { "from": "billing@yourcompany.com", "to": ["customer@example.com"], "subject": "Your invoice", "html_body": "

Invoice attached.

", "attachments": [ { "filename": "invoice.pdf", "content_type": "application/pdf", "content_base64": "" } ] } ``` **Caps:** 20 files, 10 MiB total per message. Executable / script extensions (`.exe`, `.bat`, `.js`, `.ps1`, `.sh`, …) are blocked. See [Send with attachments](/api-reference/emails/send-with-attachments) for the full reference, inline-image (CID) handling, and per-language code samples. ## Common errors | Status | Code | Meaning | |---|---|---| | 400 | `INVALID_REQUEST` | Missing required field; read `message` | | 400 | `INVALID_ATTACHMENT` | Attachment failed validation — see [Send with attachments](/api-reference/emails/send-with-attachments) | | 400 | `FROM_NOT_VERIFIED` | Verify your domain at `POST /identities` | | 400 | `TOO_MANY_RECIPIENTS` | Split into multiple sends | | 402 | `INSUFFICIENT_BALANCE` | Recharge wallet | | 403 | `SANDBOX_QUOTA_REACHED` | Daily 200/day cap hit — request production access | | 403 | `SENDING_PAUSED` | Account paused — contact support | | 429 | `RATE_LIMITED` | Per-second cap exceeded — back off | ================================================================================ # Send template Section: API Reference › Emails URL: https://email-docs.splashifypro.com/api-reference/emails/send-template ================================================================================ > POST /api/v1/partner/email/send-template — send a saved template with variables. # Send template Send a previously-saved [template](/api-reference/templates/create) with per-recipient `{{variables}}` substituted in the subject + body. ```http POST /api/v1/partner/email/send-template ``` ## Request body ```json { "from": "hello@yourcompany.com", "to": ["customer@example.com"], "template_name": "welcome", "variables": { "first_name": "Alex", "company_name": "Acme" }, "configuration_set_name": "production" } ``` | Field | Type | Required | Notes | |---|---|---|---| | `from` | string | yes | Verified identity | | `to` | string[] | yes | Up to 50 recipients | | `cc` / `bcc` | string[] | no | | | `reply_to` | string | no | | | `template_name` | string | yes | Friendly name from `POST /templates` | | `variables` | object | no | `{{key}}` tokens replaced in subject + body | | `configuration_set_name` | string | no | Event-routing scope | | `customer_id` | string | no | Downstream customer attribution | | `category` | string | no | `transactional` (default) or `marketing` | ## Response Same shape as [`/send`](/api-reference/emails/send). ## Variable substitution `{{first_name}}` and `{{ first_name }}` (with spaces) both resolve. Missing variables stay as-is in the rendered output — they don't raise errors. To enforce required variables, declare them on the template via `declared_vars`. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/send-template \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "template_name": "welcome", "variables": {"first_name": "Alex"} }' ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 404 | `TEMPLATE_NOT_FOUND` | `template_name` not registered for this account | | 400 | `RENDERING_FAILURE` | Template rendering failed (rare — most variables are forgiving) | ================================================================================ # Send bulk Section: API Reference › Emails URL: https://email-docs.splashifypro.com/api-reference/emails/send-bulk ================================================================================ > POST /api/v1/partner/email/send-bulk — one template, many recipients with per-recipient variables. # Send bulk Send a single template to up to 500 recipients across 50 destinations, each with their own variable map. Equivalent to AWS `SendBulkTemplatedEmail`. ```http POST /api/v1/partner/email/send-bulk ``` ## Request body ```json { "from": "hello@yourcompany.com", "template_name": "newsletter-june", "default_template_data": { "campaign": "june-2026" }, "destinations": [ { "to": ["alex@example.com"], "replacement_data": { "first_name": "Alex" } }, { "to": ["brett@example.com"], "replacement_data": { "first_name": "Brett" } } ], "configuration_set_name": "marketing" } ``` | Field | Type | Required | Notes | |---|---|---|---| | `from` | string | yes | Verified identity | | `template_name` | string | yes | | | `default_template_data` | object | no | Variables that apply to every recipient unless overridden | | `destinations[]` | array | yes | Up to **50 destinations** per request | | `destinations[].to` | string[] | yes | Up to **50 recipients per destination** | | `destinations[].cc` | string[] | no | | | `destinations[].bcc` | string[] | no | | | `destinations[].replacement_data` | object | no | Per-destination variable overrides — merged onto `default_template_data` | | `reply_to` | string | no | | | `configuration_set_name` | string | no | | | `customer_id` | string | no | | | `category` | string | no | `transactional` (default) or `marketing` | | `tags` | object | no | | ## Limits - 50 destinations per request - 50 recipients per destination - 500 recipients total per request For larger lists, paginate into multiple `/send-bulk` calls. ## Response ```json { "success": true, "results": [ { "destination": 0, "recipient": "alex@example.com", "message_id": "550e8400-...", "status": "queued" }, { "destination": 1, "recipient": "brett@example.com", "message_id": "660e8400-...", "status": "queued" } ] } ``` `results[].destination` is the zero-based index into your `destinations[]` array — so you can correlate per-recipient outcomes back to the destination you submitted. ## Variable resolution For each destination: 1. Start with `default_template_data` 2. Merge `destinations[i].replacement_data` on top (per-destination overrides win) 3. Substitute `{{key}}` tokens in subject + html_body + text_body ## Per-destination 4xx behaviour If one destination fails (e.g. recipient on suppression list): - That destination gets `status: rejected` + `reason` - Other destinations continue processing If a 5xx fires (template-load failure, etc.): - The entire bulk aborts - `failed_at` in the response indicates where we stopped - Already-processed destinations stay queued ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/send-bulk \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "template_name": "newsletter", "destinations": [ {"to": ["a@example.com"], "replacement_data": {"name": "A"}}, {"to": ["b@example.com"], "replacement_data": {"name": "B"}} ] }' ``` ================================================================================ # Send raw Section: API Reference › Emails URL: https://email-docs.splashifypro.com/api-reference/emails/send-raw ================================================================================ > POST /api/v1/partner/email/send-raw — send a pre-built MIME message. # Send raw Send a fully-formed MIME message (RFC 5322). For when you need control over headers, attachments, multipart structure, or DKIM-signed forwarding. Equivalent to AWS SES `SendRawEmail`. ```http POST /api/v1/partner/email/send-raw ``` ## Request body ```json { "raw_message_base64": "RnJvbTogaGVsbG9AeW91cmNvbXBhbnkuY29tDQpUbzogY3VzdG9tZXJAZXhhbXBsZS5jb20NClN1YmplY3Q6IEhlbGxvDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KSGVsbG8h", "configuration_set_name": "production" } ``` | Field | Type | Required | Notes | |---|---|---|---| | `raw_message_base64` | string | yes | base64-encoded RFC 5322 message. Max 10 MB decoded. | | `from` | string | no | Override From-address parsing. Defaults to parsing the message's `From:` header | | `to` | string[] | no | Override recipient parsing. Defaults to parsing `To:` header | | `configuration_set_name` | string | no | | | `customer_id` | string | no | | | `category` | string | no | | | `tags` | object | no | | ## What you control - **All headers** — From, To, Cc, Bcc, Subject, Reply-To, Message-ID, arbitrary `X-` headers, `In-Reply-To`, `References` - **MIME structure** — multipart/alternative, multipart/mixed, multipart/related (inline images via `Content-ID:`) - **Attachments** — encode each part with the right Content-Type + Content-Disposition + Content-Transfer-Encoding - **Custom headers** — anything not on the reserved list ## What we override - `Date:` — set to send time if missing - `Message-ID:` — added if missing - DKIM-Signature — we always sign with our shared key - Return-Path — set to our bounce address for VERP routing ## When to use this - Sending forwarded mail with original headers preserved - Replying inside an existing thread (`In-Reply-To` / `References`) - Multipart with attachments - Custom List-Id / List-Help / List-Subscribe / List-Unsubscribe headers For simple HTML+text sends, use [`/send`](/api-reference/emails/send) — much less ceremony. ## Example Building a multipart message in Node: ```js import { createMimeMessage } from "mimetext"; const msg = createMimeMessage(); msg.setSender("hello@yourcompany.com"); msg.setRecipient("customer@example.com"); msg.setSubject("Receipt + invoice attached"); msg.addMessage({ contentType: "text/plain", data: "See attached." }); msg.addMessage({ contentType: "text/html", data: "

See attached.

" }); msg.addAttachment({ filename: "invoice.pdf", contentType: "application/pdf", data: pdfBase64, }); const raw = msg.asEncoded(); const rawB64 = Buffer.from(raw).toString("base64"); await fetch("https://api.splashifypro.com/api/v1/partner/email/send-raw", { method: "POST", headers: { Authorization: `Bearer ${API_KEY}` }, body: JSON.stringify({ raw_message_base64: rawB64 }), }); ``` ================================================================================ # Send with attachments Section: API Reference › Emails URL: https://email-docs.splashifypro.com/api-reference/emails/send-with-attachments ================================================================================ > Attach PDFs, images, documents, and other files to your emails. Supported on /send, /send-template, and /send-bulk. # Send with attachments Three of the four send endpoints accept an `attachments[]` array — `/send`, `/send-template`, and `/send-bulk`. Each attachment carries the file bytes inline as base64; we build the `multipart/mixed` MIME structure for you, DKIM-sign it, and ship it to the recipient through the same pipeline as plain-body emails. `/send-raw` always supported attachments because customers build the MIME themselves. See [Send raw](/api-reference/emails/send-raw) for that path. ## Attachment object Each entry in `attachments[]` is shaped like this: ```json { "filename": "invoice-2026-04.pdf", "content_type": "application/pdf", "content_base64": "", "content_id": "logo-header", "inline": false } ``` | Field | Type | Required | Meaning | |---|---|---|---| | `filename` | string | yes | Displayed by the recipient's mail client. Auto-sanitized — directory separators + control chars stripped. | | `content_type` | string | optional | MIME type (e.g. `application/pdf`). When omitted, we infer from the filename extension. Falls back to `application/octet-stream`. | | `content_base64` | string | yes | Standard base64 encoding of the file bytes. **Not** URL-safe base64 — use the standard alphabet. | | `content_id` | string | optional | Sets `Content-ID` so HTML can reference the attachment as ``. Pair with `inline: true`. | | `inline` | boolean | optional | When `true`, sets `Content-Disposition: inline` (image renders in the body). When `false` (default), sets `attachment` (file appears in the recipient's attachments list). | ## Limits | Cap | Value | What happens when exceeded | |---|---|---| | Files per message | **20** | Returns `400 INVALID_ATTACHMENT` with `"max 20 attachments per message"` | | Total decoded bytes | **10 MiB** | Returns `400 INVALID_ATTACHMENT` with the bytes-cap message. Sum runs across all attachments — a single 10.1 MiB PDF is rejected just like 11 × 1 MiB files. | | Filename length | 256 chars | Rejected at validation. | | Content-Type length | 256 chars | Rejected at validation. | ## Blocked file types Executable + script extensions are refused at the API layer because recipient mail providers (Gmail, Outlook, corporate gateways) block them outright — sending one would cost a wallet deduction for a guaranteed bounce. Blocked extensions: `.exe` `.bat` `.cmd` `.com` `.scr` `.msi` `.vbs` `.vbe` `.js` `.jse` `.wsf` `.wsh` `.ps1` `.dll` `.jar` `.app` `.sh` `.pl` `.py` `.lnk` Workaround: bundle them inside a `.zip`. ZIPs are allowed. ## Example — single PDF ```bash ATT=$(base64 -i invoice.pdf | tr -d '\n') curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer pk_live_…" \ -H "Content-Type: application/json" \ -d "{ \"from\": \"billing@yourcompany.com\", \"to\": [\"customer@example.com\"], \"subject\": \"Invoice for March\", \"html_body\": \"

Hi! Your invoice for March is attached.

\", \"attachments\": [ { \"filename\": \"invoice-march-2026.pdf\", \"content_type\": \"application/pdf\", \"content_base64\": \"$ATT\" } ] }" ``` ## Example — Node.js (multiple files) ```js import { readFileSync } from 'node:fs' const toAtt = (path, contentType) => ({ filename: path.split('/').pop(), content_type: contentType, content_base64: readFileSync(path).toString('base64'), }) const r = await fetch('https://api.splashifypro.com/api/v1/partner/email/send', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.SPLASHIFY_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ from: 'billing@yourcompany.com', to: ['customer@example.com'], subject: 'Your March documents', html_body: '

Attached: invoice + receipt + signed contract.

', attachments: [ toAtt('./invoice.pdf', 'application/pdf'), toAtt('./receipt.pdf', 'application/pdf'), toAtt('./contract.pdf', 'application/pdf'), ], }), }) console.log(await r.json()) ``` ## Example — Python ```python import base64, requests, os def att(path, ct): with open(path, 'rb') as f: return { 'filename': os.path.basename(path), 'content_type': ct, 'content_base64': base64.b64encode(f.read()).decode(), } r = requests.post( 'https://api.splashifypro.com/api/v1/partner/email/send', headers={'Authorization': f"Bearer {os.environ['SPLASHIFY_API_KEY']}"}, json={ 'from': 'support@yourcompany.com', 'to': ['customer@example.com'], 'subject': 'Attached photo', 'html_body': '

Here\'s the photo from your visit.

', 'attachments': [att('./photo.jpg', 'image/jpeg')], }, ) print(r.json()) ``` ## Example — Inline image (CID reference) When you want the image to render **inside** the email body instead of as a separate downloadable file, use `inline: true` + `content_id`, then reference it from your HTML with `cid:`: ```json { "from": "newsletter@yourcompany.com", "to": ["customer@example.com"], "subject": "Today's newsletter", "html_body": "

Welcome!

", "attachments": [ { "filename": "banner.png", "content_type": "image/png", "content_base64": "iVBORw0KGgo…", "content_id": "hero-banner", "inline": true } ] } ``` Most modern mail clients (Gmail web + mobile, Outlook, Apple Mail) render inline images correctly. A few hardened corporate gateways strip them — the file falls back to a regular attachment in those. ## Errors | Status | Code | Reason | |---|---|---| | 400 | `INVALID_ATTACHMENT` | Too many files, total size exceeded, blocked extension, invalid base64, or empty content | | 400 | `FROM_NOT_VERIFIED` | From-address not on a verified identity (same as plain send) | | 402 | `INSUFFICIENT_BALANCE` | Wallet too low to cover the per-recipient send cost | ## Pricing Attachments do **not** incur a per-byte charge. You're billed at the per-recipient rate (₹0.03 per email, marketing or transactional) regardless of attachment size. The only practical cost is the 10 MiB total cap which limits how big each individual message can be. ## Best practices - **Compress where you can.** A PDF with images compressed to 200 dpi vs 600 dpi can be 5× smaller and still look perfect at on-screen resolution. Smaller messages deliver faster + use less of your 10 MiB budget. - **Use links for files > 5 MiB.** Recipient mail providers throttle large messages and some flag them as suspicious. For anything bigger, host on object storage and put a download link in the body. - **Set `content_type` explicitly when you can** — saves us a filename-extension guess. The mail client's "open with" picker uses this header. - **Prefer real filenames.** Generic `attachment.pdf` is allowed but hurts deliverability slightly (Gmail's spam filter weights template-shaped filenames). `invoice-march-2026.pdf` is better. ## Send-bulk semantics When you call `/send-bulk` with `attachments[]`, the same files are attached to **every** destination's email — there's no per-recipient attachment override. If you need different attachments per recipient, call `/send-template` once per recipient instead. ================================================================================ # Get email status Section: API Reference › Emails URL: https://email-docs.splashifypro.com/api-reference/emails/get-status ================================================================================ > GET /api/v1/partner/email/emails/:message_id — check the delivery state of a sent email. # Get email status Check whether a sent email has been queued, delivered, bounced, or rejected. ```http GET /api/v1/partner/email/emails/:message_id ``` ## Path parameters | Field | Notes | |---|---| | `message_id` | UUID returned from `/send` / `/send-template` / `/send-bulk` / `/send-raw` | ## Response ```json { "success": true, "message_id": "550e8400-e29b-41d4-a716-446655440000", "status": "delivered", "from_address": "hello@yourcompany.com", "to_address": "customer@example.com", "subject": "Welcome", "category": "transactional", "smtp_message_id": "", "created_at": "2026-05-03T12:34:56Z", "sent_at": "2026-05-03T12:34:57Z", "delivered_at": "2026-05-03T12:34:57Z" } ``` ## Status values | Status | Meaning | |---|---| | `queued` | API accepted; not yet delivered to recipient MX | | `sent` | Sent to recipient MX (collapsed with `delivered` for our pipeline) | | `delivered` | Recipient MX returned 250 OK | | `bounced` | Hard or soft-bounce-exhausted bounce | | `complained` | Recipient marked as spam (FBL report received) | | `rejected` | Refused pre-SMTP (suppression list, sandbox cap, etc.) | | `failed` | Soft bounce retries exhausted | ## Bounce details When `status: bounced`: ```json { "status": "bounced", "bounced_at": "2026-05-03T12:35:01Z", "bounce_type": "Permanent", "bounce_reason": "no_such_user" } ``` ## When to use polling vs webhooks **Polling is the wrong default.** Webhooks (set up via [event destinations](/api-reference/event-destinations/create)) push status changes to your server within seconds without you polling. Use this endpoint for: - One-off lookups (debugging a specific send) - UI surfaces showing live status (after a webhook update lands) - Reconciliation jobs (check that webhook delivery wasn't dropped) Don't poll every send every 5 seconds — wasteful for both sides. ## Common errors | Status | Code | Meaning | |---|---|---| | 404 | `MESSAGE_NOT_FOUND` | Message id doesn't match any send. Possible: wrong account, malformed id, or message older than retention window | ## Retention Outbox rows are retained for 30 days. After that, older rows return 404. For long-term audit, listen to the `Send` / `Delivery` / `Bounce` webhook events and persist them yourself. ================================================================================ # List templates Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/list ================================================================================ > GET /api/v1/partner/email/templates # List templates ```http GET /api/v1/partner/email/templates ``` ## Response ```json { "success": true, "templates": [ { "template_id": "tpl_550e8400-...", "template_name": "welcome", "subject": "Welcome to {{company_name}}", "declared_vars": ["first_name", "company_name"], "created_at": "2026-05-03T12:00:00Z", "updated_at": "2026-05-03T12:00:00Z" } ], "count": 1 } ``` `html` + `text` + `react_email_json` are NOT included in list responses to keep the payload small. Use [GET /templates/:id](/api-reference/templates/get) or [GET /templates/by-name/:name](/api-reference/templates/get-by-name) to fetch full content. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/templates \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Create template Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/create ================================================================================ > POST /api/v1/partner/email/templates # Create template Save a reusable template. Reference it on `/send-template` or `/send-bulk` by its `template_name`. ```http POST /api/v1/partner/email/templates ``` ## Request body ```json { "template_name": "welcome", "subject": "Welcome to {{company_name}}, {{first_name}}", "html": "

Hi {{first_name}} 👋

Thanks for joining {{company_name}}.

", "text": "Hi {{first_name}}. Thanks for joining {{company_name}}.", "declared_vars": ["first_name", "company_name"] } ``` | Field | Type | Required | Notes | |---|---|---|---| | `template_name` | string | yes | Unique per account. Lowercase letters / numbers / `_` `-`, max 64 chars | | `subject` | string | yes | Variables can be used here too | | `html` | string | conditional | One of `html` or `react_email_json` is required | | `text` | string | no | Plaintext fallback. Auto-derived from HTML if omitted | | `react_email_json` | string | conditional | Visual-editor JSON. Renders to `html` + `text` server-side | | `declared_vars` | string[] | no | Variable names the template uses. Surfaced on the panel + helps catch typos | ## Variable syntax Both `{{var_name}}` and `{{ var_name }}` (with spaces) work. Missing variables at send time stay as the literal `{{name}}` in the rendered output rather than raising an error — this keeps hot-path sends forgiving. To enforce required variables, declare them in `declared_vars` and validate yourself before calling `/send-template`. ## Response ```json { "success": true, "template": { "template_id": "tpl_550e8400-...", "template_name": "welcome", "subject": "Welcome to {{company_name}}, {{first_name}}", "html": "

Hi {{first_name}}...", "text": "Hi {{first_name}}...", "declared_vars": ["first_name", "company_name"], "created_at": "...", "updated_at": "..." } } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/templates \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "template_name": "welcome", "subject": "Hi {{first_name}}", "html": "

Hi {{first_name}}

" }' ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 409 | `TEMPLATE_NAME_TAKEN` | Another template with that name exists | | 400 | `INVALID_REQUEST` | Bad name format or missing both `html` and `react_email_json` | | 400 | `TEMPLATE_LIMIT_REACHED` | 500-template cap per account | ================================================================================ # Get template Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/get ================================================================================ > GET /api/v1/partner/email/templates/:id # Get template ```http GET /api/v1/partner/email/templates/:id ``` Fetch full template content by template_id. ## Response ```json { "success": true, "template": { "template_id": "tpl_550e8400-...", "template_name": "welcome", "subject": "Welcome", "html": "

Hi {{first_name}}

", "text": "Hi {{first_name}}", "react_email_json": "...", "declared_vars": ["first_name"], "created_at": "...", "updated_at": "..." } } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/templates/tpl_550e8400-... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Get template by name Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/get-by-name ================================================================================ > GET /api/v1/partner/email/templates/by-name/:name # Get template by name ```http GET /api/v1/partner/email/templates/by-name/:name ``` Fetch a template by its `template_name`. Same response shape as [GET /templates/:id](/api-reference/templates/get). Useful when your code only knows the friendly name (e.g. from a config file) and not the UUID. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/templates/by-name/welcome \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Update template Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/update ================================================================================ > PATCH /api/v1/partner/email/templates/:id # Update template ```http PATCH /api/v1/partner/email/templates/:id ``` All fields optional — pass only what's changing. `template_name` cannot be changed; create a new template under the new name and delete the old one. ## Request body ```json { "subject": "Welcome to {{company_name}}", "html": "

Updated welcome 👋

", "text": "Updated welcome.", "declared_vars": ["company_name"] } ``` | Field | Type | Notes | |---|---|---| | `subject` | string | | | `html` | string | | | `text` | string | | | `react_email_json` | string | When supplied, re-renders to fresh `html` + `text` | | `declared_vars` | string[] | Replaces existing list | ## cURL ```bash curl -X PATCH \ https://api.splashifypro.com/api/v1/partner/email/templates/tpl_550e8400-... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"subject": "New subject"}' ``` ================================================================================ # Delete template Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/delete ================================================================================ > DELETE /api/v1/partner/email/templates/:id # Delete template ```http DELETE /api/v1/partner/email/templates/:id ``` Removes the template + its name alias. In-flight `/send-template` calls referencing this template by name return `404 TEMPLATE_NOT_FOUND` after the delete commits. ## cURL ```bash curl -X DELETE \ https://api.splashifypro.com/api/v1/partner/email/templates/tpl_550e8400-... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## What this does NOT do - Does NOT recall already-queued sends that referenced this template. - Does NOT remove historical send records — `GET /emails/:message_id` still returns the original `template_id` for past sends. ================================================================================ # Preview template Section: API Reference › Templates URL: https://email-docs.splashifypro.com/api-reference/templates/preview ================================================================================ > POST /api/v1/partner/email/templates/preview — render visual-editor JSON without persisting. # Preview template Render a `react_email_json` payload to HTML + plaintext without saving a template. Useful for live preview UIs in your panel before you persist via `POST /templates`. ```http POST /api/v1/partner/email/templates/preview ``` ## Request body ```json { "react_email_json": "{...}", "variables": { "first_name": "Alex", "company_name": "Acme" } } ``` | Field | Type | Required | Notes | |---|---|---|---| | `react_email_json` | string | yes | Visual-editor block JSON | | `variables` | object | no | Substitution map applied to the rendered output | ## Response ```json { "success": true, "html": "...", "text": "..." } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/templates/preview \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "react_email_json": "...", "variables": {"first_name": "Alex"} }' ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 503 | `RENDERER_UNAVAILABLE` | Template rendering service is temporarily down — retry | | 502 | `RENDER_FAILED` | The JSON couldn't be compiled. Read the message | ================================================================================ # List audiences Section: API Reference › Audiences URL: https://email-docs.splashifypro.com/api-reference/audiences/list ================================================================================ > GET /api/v1/partner/email/audiences: every audience of your account with its contact counts. # List audiences Every audience (contact list) of your account, with how many contacts are subscribed, unsubscribed and bounced. ```http GET /api/v1/partner/email/audiences ``` Connected apps need `email.contacts:write` or `email.contacts:read`. See [Connected apps (OAuth)](/api-reference/connected-apps). ## Response ```json { "success": true, "audiences": [ { "audience_id": "8b2f6c1e-9a4d-4f1b-b6a2-1c3d5e7f9a0b", "name": "Newsletter", "description": "Monthly product news", "subscribed": 1240, "unsubscribed": 37, "bounced": 12, "total": 1289, "created_at": "2026-08-14T06:30:00Z", "updated_at": "2026-09-30T11:02:00Z" } ] } ``` | Field | Meaning | |---|---| | `audience_id` | Use it in the other audience calls | | `subscribed`, `unsubscribed`, `bounced` | Contacts in each status | | `total` | Every contact ever added to the audience | All audiences come in one answer; there is no paging. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/audiences \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Common errors | Status | `message` | Why | |---|---|---| | 401 | `unauthorized` | Missing or wrong key or token | | 500 | `database error` | Try again in a moment | ================================================================================ # Get audience Section: API Reference › Audiences URL: https://email-docs.splashifypro.com/api-reference/audiences/get ================================================================================ > GET /api/v1/partner/email/audiences/:id: one audience with its contact counts. # Get audience One audience with its contact counts. ```http GET /api/v1/partner/email/audiences/:id ``` Connected apps need `email.contacts:write` or `email.contacts:read`. See [Connected apps (OAuth)](/api-reference/connected-apps). ## Path parameters | Field | Type | Notes | |---|---|---| | `id` | uuid | The `audience_id` from [List audiences](/api-reference/audiences/list) | ## Response ```json { "success": true, "audience": { "audience_id": "8b2f6c1e-9a4d-4f1b-b6a2-1c3d5e7f9a0b", "name": "Newsletter", "description": "Monthly product news", "subscribed": 1240, "unsubscribed": 37, "bounced": 12, "total": 1289, "created_at": "2026-08-14T06:30:00Z", "updated_at": "2026-09-30T11:02:00Z" } } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/audiences/8b2f6c1e-9a4d-4f1b-b6a2-1c3d5e7f9a0b \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Common errors | Status | `message` | Why | |---|---|---| | 400 | `invalid audience_id` | `id` is not a UUID | | 401 | `unauthorized` | Missing or wrong key or token | | 404 | `audience not found` | No audience with this id on your account | ================================================================================ # List contacts Section: API Reference › Audiences URL: https://email-docs.splashifypro.com/api-reference/audiences/list-contacts ================================================================================ > GET /api/v1/partner/email/audiences/:id/contacts: the contacts of an audience, 50 at a time, in email order. # List contacts The contacts of one audience, 50 at a time, in email address order. ```http GET /api/v1/partner/email/audiences/:id/contacts ``` Connected apps need `email.contacts:read`, which only verified apps can have. See [Connected apps (OAuth)](/api-reference/connected-apps). ## Parameters | Field | In | Notes | |---|---|---| | `id` | path | The `audience_id` | | `cursor` | query | The `next_cursor` of the previous page. Leave it out for the first page. | | `status` | query | Only contacts in this status: `subscribed`, `unsubscribed`, `bounced` or `complained` | ## Response ```json { "success": true, "contacts": [ { "email": "asha@example.com", "status": "subscribed", "first_name": "Asha", "last_name": "Rao", "attributes": { "city": "Pune" }, "created_at": "2026-09-01T08:00:00Z" } ], "next_cursor": "asha@example.com" } ``` `next_cursor` is there when more contacts may follow. Pass it as `cursor` to get the next page, and stop when it is missing. With a `status` filter, each page is read first and then filtered, so a page can hold fewer than 50 contacts, or none, while `next_cursor` is still there. Keep paging until `next_cursor` is missing. ## cURL ```bash curl "https://api.splashifypro.com/api/v1/partner/email/audiences/8b2f6c1e-9a4d-4f1b-b6a2-1c3d5e7f9a0b/contacts?status=subscribed" \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Common errors | Status | `message` | Why | |---|---|---| | 400 | `invalid audience_id` | `id` is not a UUID | | 401 | `unauthorized` | Missing or wrong key or token | ================================================================================ # Add contacts Section: API Reference › Audiences URL: https://email-docs.splashifypro.com/api-reference/audiences/add-contacts ================================================================================ > POST /api/v1/partner/email/audiences/:id/contacts: add contacts to an audience. # Add contacts Add one or more contacts to an audience. ```http POST /api/v1/partner/email/audiences/:id/contacts ``` Connected apps need `email.contacts:write`. See [Connected apps (OAuth)](/api-reference/connected-apps). ## Request body ```json { "contacts": [ { "email": "asha@example.com", "first_name": "Asha", "last_name": "Rao", "attributes": { "city": "Pune" } }, { "email": "vikram@example.com" } ] } ``` | Field | Type | Required | Notes | |---|---|---|---| | `contacts` | object[] | yes | The contacts to add | | `contacts[].email` | string | yes | Stored in lower case. An address without `@` is skipped. | | `contacts[].first_name` | string | no | | | `contacts[].last_name` | string | no | | | `contacts[].attributes` | object | no | Text values, for template variables | Use an `audience_id` from [List audiences](/api-reference/audiences/list). ## Response ```json { "success": true, "added": 1, "skipped": 1 } ``` - A new email is added as `subscribed` and counts in `added`. - An email already in the audience counts in `skipped`. Its first and last name are updated, and its status stays as it was, so an unsubscribed contact is never subscribed again this way. - An invalid address counts in `skipped`. ## cURL ```bash curl -X POST https://api.splashifypro.com/api/v1/partner/email/audiences/8b2f6c1e-9a4d-4f1b-b6a2-1c3d5e7f9a0b/contacts \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"contacts":[{"email":"asha@example.com","first_name":"Asha"}]}' ``` ## Common errors | Status | `message` | Why | |---|---|---| | 400 | `invalid audience_id` | `id` is not a UUID | | 400 | `invalid body` | The body is not JSON in the shape above | | 401 | `unauthorized` | Missing or wrong key or token | ================================================================================ # Update contact Section: API Reference › Audiences URL: https://email-docs.splashifypro.com/api-reference/audiences/update-contact ================================================================================ > PATCH /api/v1/partner/email/audiences/:id/contacts/:email: change a contact's status or name. # Update contact Change the status or name of a contact in an audience, for example to unsubscribe someone who asked you to stop. ```http PATCH /api/v1/partner/email/audiences/:id/contacts/:email ``` Connected apps need `email.contacts:write`. See [Connected apps (OAuth)](/api-reference/connected-apps). ## Path parameters | Field | Notes | |---|---| | `id` | The `audience_id` | | `email` | The contact's email address, **URL-encoded**: `asha@example.com` becomes `asha%40example.com`, and `a+b@example.com` becomes `a%2Bb%40example.com`. Any case; it is matched in lower case. | ## Request body Send any of these fields; the others stay as they are. ```json { "status": "unsubscribed", "first_name": "Asha", "last_name": "Rao" } ``` | Field | Notes | |---|---| | `status` | `subscribed`, `unsubscribed`, `bounced` or `complained`. Any other value is saved as `subscribed`. | | `first_name` | | | `last_name` | | Update only contacts that are in the audience: add a new address with [Add contacts](/api-reference/audiences/add-contacts) first. ## Response ```json { "success": true } ``` ## cURL ```bash curl -X PATCH https://api.splashifypro.com/api/v1/partner/email/audiences/8b2f6c1e-9a4d-4f1b-b6a2-1c3d5e7f9a0b/contacts/asha%40example.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status":"unsubscribed"}' ``` ## Common errors | Status | `message` | Why | |---|---|---| | 400 | `invalid audience_id` | `id` is not a UUID | | 400 | `email required` | The email in the path is empty | | 400 | `invalid body` | The body is not JSON in the shape above | | 401 | `unauthorized` | Missing or wrong key or token | ================================================================================ # List identities Section: API Reference › Identities URL: https://email-docs.splashifypro.com/api-reference/identities/list ================================================================================ > GET /api/v1/partner/email/identities # List identities ```http GET /api/v1/partner/email/identities ``` Lists every sending identity (verified domains + email addresses) configured for your account. ## Response ```json { "success": true, "identities": [ { "identity_type": "DOMAIN", "identity_value": "yourcompany.com", "status": "VERIFIED", "spf_ok": true, "dkim_ok": true, "dmarc_ok": true, "verified_at": "2026-05-03T12:00:00Z", "created_at": "2026-05-03T11:55:00Z" } ], "count": 1 } ``` ## Status values | Status | Meaning | |---|---| | `PENDING` | DNS records not yet verified | | `VERIFIED` | All three records pass — ready to send | | `FAILED` | Verification failed multiple times — re-trigger via `POST /verify` | | `TEMPORARY_FAILURE` | DNS lookup error — retry | ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Create identity Section: API Reference › Identities URL: https://email-docs.splashifypro.com/api-reference/identities/create ================================================================================ > POST /api/v1/partner/email/identities — register a new domain or email address. # Create identity Register a new sending identity. Returns the DNS records you need to publish (for `DOMAIN`) or a verification token (for `EMAIL_ADDRESS`). ```http POST /api/v1/partner/email/identities ``` ## Request body ```json { "identity_type": "DOMAIN", "identity_value": "yourcompany.com" } ``` | Field | Type | Required | Notes | |---|---|---|---| | `identity_type` | string | yes | `DOMAIN` or `EMAIL_ADDRESS` | | `identity_value` | string | yes | The domain (e.g. `yourcompany.com`) or full email address | ## Response For `DOMAIN`: ```json { "success": true, "identity_type": "DOMAIN", "identity_value": "yourcompany.com", "status": "PENDING", "dns_records": { "spf": {"type": "TXT", "hostname": "yourcompany.com", "value": "v=spf1 include:_spf.mail.splashifypro.com ~all"}, "dkim": {"type": "CNAME", "hostname": "splashify._domainkey.yourcompany.com", "value": "splashify._domainkey.mail.splashifypro.com"}, "dmarc": {"type": "TXT", "hostname": "_dmarc.yourcompany.com", "value": "v=DMARC1; p=quarantine; rua=mailto:dmarc@splashifypro.com"} } } ``` Publish every record in `dns_records` on your DNS provider (SPF, DKIM and DMARC, plus `dkim2` and `return_path` when present), then call [`/verify`](/api-reference/identities/verify) to confirm. For `EMAIL_ADDRESS`: ```json { "success": true, "identity_type": "EMAIL_ADDRESS", "identity_value": "alerts@yourcompany.com", "status": "PENDING", "verification_token": "abc123..." } ``` We email a confirmation link to the address. Click it (or POST the token via `/verify`) to mark the identity verified. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"identity_type": "DOMAIN", "identity_value": "yourcompany.com"}' ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 400 | `INVALID_REQUEST` | Bad domain format / invalid email | | 400 | `PUBLIC_DOMAIN_BLOCKED` | Public-mail-provider domain (gmail.com, yahoo.com, etc.) — not allowed | | 400 | `IDENTITY_LIMIT_REACHED` | Sandbox account hit the 25-identity cap. The cap is **lifted automatically** once production access is approved — see below. | ### About the identity cap | Account state | Identity cap | |---|---| | **Sandbox** (default for new accounts) | **25** identities (domains + email addresses combined) | | **Production access approved** | **Unlimited** | Most accounts only need 1 – 5 identities even at full scale. Verifying a single domain (e.g. `mail.yourcompany.com`) authorizes every `@mail.yourcompany.com` to send, so you rarely need to register individual email addresses separately. #### Lifting the cap The cleanest path is **production access** — admin reviews your use case once, approves, and the identity cap is removed automatically along with the daily-send cap (200/day → 50,000/day) and peak-rate cap (1/sec → 14/sec). Submit at `POST /partner/email/production-access` or via the **Production Access** tab in Splashify Pro Email. #### Working around the cap before production access If you're still in sandbox and genuinely need to register a new identity but already have 25: 1. List what's registered — `GET /partner/email/identities`. 2. Delete one you no longer send from — `DELETE /partner/email/identities/{type}/{value}`. 3. The slot frees immediately; re-try the create call. If your sandbox use case legitimately needs more than 25 identities (rare — usually means you're adding one `EMAIL_ADDRESS` per customer where verifying the parent domain would do), email support@splashifypro.in with the use case. ================================================================================ # Get identity Section: API Reference › Identities URL: https://email-docs.splashifypro.com/api-reference/identities/get ================================================================================ > GET /api/v1/partner/email/identities/:type/:value # Get identity ```http GET /api/v1/partner/email/identities/:type/:value ``` Returns the current state of one identity, including a **live DNS-check overlay** so you see real-time `spf_ok` / `dkim_ok` / `dmarc_ok` flags reflecting what's actually published right now. ## Path parameters | Field | Notes | |---|---| | `type` | `DOMAIN` or `EMAIL_ADDRESS` | | `value` | The domain or email address | ## Response ```json { "success": true, "identity": { "identity_type": "DOMAIN", "identity_value": "yourcompany.com", "status": "VERIFIED", "spf_ok": true, "dkim_ok": true, "dmarc_ok": true, "dkim_selector": "splashify", "verified_at": "2026-05-03T12:00:00Z", "created_at": "2026-05-03T11:55:00Z", "dns_records": { "spf": {"pass": true, "found": "v=spf1 include:_spf.mail.splashifypro.com ~all", "expected": "..."}, "dkim": {"pass": true, "found": "CNAME splashify._domainkey.mail.splashifypro.com", "expected": "..."}, "dmarc": {"pass": true, "found": "v=DMARC1; p=quarantine; ...", "expected": "..."} } } } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Verify identity Section: API Reference › Identities URL: https://email-docs.splashifypro.com/api-reference/identities/verify ================================================================================ > POST /api/v1/partner/email/identities/:type/:value/verify — re-run DNS / token check. # Verify identity Re-run DNS verification for a domain identity (after publishing records), or confirm an email-address identity (with the verification token). ```http POST /api/v1/partner/email/identities/:type/:value/verify ``` ## Domain verification ```bash curl -X POST \ https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com/verify \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Response: ```json { "success": true, "status": "VERIFIED", "spf_ok": true, "dkim_ok": true, "dmarc_ok": true, "dns_records": { ... } } ``` When all three records pass, status flips to `VERIFIED`. If any record fails, status stays `PENDING` (or flips to `FAILED` after multiple unsuccessful attempts) — the per-record `pass` flags tell you which records to fix. ## Email-address verification ```bash curl -X POST \ https://api.splashifypro.com/api/v1/partner/email/identities/EMAIL_ADDRESS/alerts@yourcompany.com/verify \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"token": "abc123..."}' ``` The token is the `verification_token` returned from [`POST /identities`](/api-reference/identities/create). ## Rate limiting We rate-limit re-verify calls to **once per 60 seconds per identity** to prevent DNS-server hammering. Calls inside the window return `429 RATE_LIMITED`. ## Auto-recheck behaviour We automatically re-check: - **Pending** identities every 1 hour for 7 days - **Verified** identities every 24 hours If a verified domain's records disappear, status flips back to `PENDING` and we email you. You can always trigger a manual re-check via this endpoint. ================================================================================ # Delete identity Section: API Reference › Identities URL: https://email-docs.splashifypro.com/api-reference/identities/delete ================================================================================ > DELETE /api/v1/partner/email/identities/:type/:value # Delete identity Remove a sending identity. In-flight sends from that identity complete normally; new sends are rejected with `FROM_NOT_VERIFIED`. ```http DELETE /api/v1/partner/email/identities/:type/:value ``` ## cURL ```bash curl -X DELETE \ https://api.splashifypro.com/api/v1/partner/email/identities/DOMAIN/yourcompany.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Response ```json { "success": true } ``` ## What this does NOT do - Does NOT delete your DNS records — you can leave them published and re-add the identity later - Does NOT clear the suppression list — recipient suppressions are account-wide, not per-identity - Does NOT remove webhook destinations — those live on configuration sets, not identities ## Reactivating To re-add a deleted identity, just `POST /identities` again with the same value. If your DNS records are still published, the verification will pass on first check and the identity is back to `VERIFIED` immediately. ================================================================================ # List configuration sets Section: API Reference › Configuration Sets URL: https://email-docs.splashifypro.com/api-reference/configuration-sets/list ================================================================================ > GET /api/v1/partner/email/configuration-sets # List configuration sets ```http GET /api/v1/partner/email/configuration-sets ``` ## Query parameters | Field | Type | Notes | |---|---|---| | `customer_id` | uuid | Filter by downstream customer attribution | ## Response ```json { "success": true, "configuration_sets": [ { "config_set_id": "cs_550e8400-...", "name": "production", "description": "Production transactional sends", "sending_enabled": true, "reputation_tracking_enabled": true, "suppression_options": "BOUNCE_AND_COMPLAINT", "tags": {"env": "prod"}, "created_at": "2026-05-03T12:00:00Z", "updated_at": "2026-05-03T12:00:00Z" } ], "count": 1 } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Create configuration set Section: API Reference › Configuration Sets URL: https://email-docs.splashifypro.com/api-reference/configuration-sets/create ================================================================================ > POST /api/v1/partner/email/configuration-sets # Create configuration set ```http POST /api/v1/partner/email/configuration-sets ``` ## Request body ```json { "name": "production", "description": "Production transactional sends", "customer_id": "cust_550e8400-...", "sending_enabled": true, "reputation_tracking_enabled": true, "suppression_options": "BOUNCE_AND_COMPLAINT", "tags": { "env": "prod", "team": "platform" } } ``` | Field | Type | Required | Notes | |---|---|---|---| | `name` | string | yes | Unique per account, alphanumeric + `_` `-`, 1-256 chars | | `description` | string | no | | | `customer_id` | uuid | no | Downstream end-customer attribution | | `sending_enabled` | bool | no | Default `true` | | `reputation_tracking_enabled` | bool | no | Default `true` | | `suppression_options` | string | no | `NONE` / `BOUNCE` / `COMPLAINT` / `BOUNCE_AND_COMPLAINT` (default) | | `custom_redirect_domain` | string | no | Per-config-set click-tracking host | | `tags` | object | no | Arbitrary key-value pairs surfaced on `mail.tags` in webhooks | ## Response ```json { "success": true, "configuration_set": { "config_set_id": "cs_550e8400-...", "name": "production", ... } } ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 409 | `CONFIG_SET_NAME_TAKEN` | Another set with that name exists | | 400 | `INVALID_REQUEST` | Bad `suppression_options` value or missing `name` | ================================================================================ # Get configuration set Section: API Reference › Configuration Sets URL: https://email-docs.splashifypro.com/api-reference/configuration-sets/get ================================================================================ > GET /api/v1/partner/email/configuration-sets/:id # Get configuration set ```http GET /api/v1/partner/email/configuration-sets/:id ``` ## Path parameters | Field | Notes | |---|---| | `id` | The `config_set_id` returned from `POST /configuration-sets` | ## Response ```json { "success": true, "configuration_set": { "config_set_id": "cs_550e8400-...", "name": "production", "description": "...", "sending_enabled": true, "reputation_tracking_enabled": true, "suppression_options": "BOUNCE_AND_COMPLAINT", "tags": {"env": "prod"}, "created_at": "...", "updated_at": "..." } } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_550e8400-... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Update configuration set Section: API Reference › Configuration Sets URL: https://email-docs.splashifypro.com/api-reference/configuration-sets/update ================================================================================ > PATCH /api/v1/partner/email/configuration-sets/:id # Update configuration set ```http PATCH /api/v1/partner/email/configuration-sets/:id ``` All fields are optional — pass only what you want to change. Common use: kill-switch a set with `sending_enabled: false`, toggle suppression behaviour, rename. ## Request body ```json { "name": "production-v2", "sending_enabled": false, "suppression_options": "BOUNCE", "tags": { "env": "prod", "version": "v2" } } ``` | Field | Type | Notes | |---|---|---| | `name` | string | Must remain unique per account | | `description` | string | | | `sending_enabled` | bool | Disable to halt new sends through this set | | `reputation_tracking_enabled` | bool | | | `suppression_options` | string | `NONE` / `BOUNCE` / `COMPLAINT` / `BOUNCE_AND_COMPLAINT` | | `custom_redirect_domain` | string | | | `tags` | object | Replaces existing tags entirely (not merge) | ## cURL ```bash curl -X PATCH \ https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_550e8400-... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"sending_enabled": false}' ``` ================================================================================ # Delete configuration set Section: API Reference › Configuration Sets URL: https://email-docs.splashifypro.com/api-reference/configuration-sets/delete ================================================================================ > DELETE /api/v1/partner/email/configuration-sets/:id # Delete configuration set Cascades — deletes the configuration set + every event destination attached to it. ```http DELETE /api/v1/partner/email/configuration-sets/:id ``` ## cURL ```bash curl -X DELETE \ https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_550e8400-... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## What this does NOT do - Doesn't delete the historical events / stats associated with this config set — they're still accessible via `GET /events` and `GET /stats?config_set_id=...` - Doesn't suppress in-flight sends. New sends referencing the deleted set's name return `404 CONFIG_SET_NOT_FOUND`. ## Reactivating Create a new config set with the same `name`. It gets a fresh `config_set_id` — old `message_id` records still reference the old id but new sends use the new one. ================================================================================ # List event destinations Section: API Reference › Event Destinations URL: https://email-docs.splashifypro.com/api-reference/event-destinations/list ================================================================================ > GET /api/v1/partner/email/configuration-sets/:id/event-destinations # List event destinations ```http GET /api/v1/partner/email/configuration-sets/:id/event-destinations ``` Returns every webhook destination attached to a configuration set. ## Response ```json { "success": true, "event_destinations": [ { "destination_id": "ed_550e8400-...", "name": "production-webhook", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/email", "is_signed": true, "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"], "enabled": true, "created_at": "2026-05-03T12:00:00Z", "updated_at": "2026-05-03T12:00:00Z" } ], "count": 1 } ``` `is_signed` is `true` when a `webhook_secret` is configured. The secret value itself is **never** returned by the API — to verify you have the right one, send a test event and check that your endpoint's HMAC validation passes. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_.../event-destinations \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Create event destination Section: API Reference › Event Destinations URL: https://email-docs.splashifypro.com/api-reference/event-destinations/create ================================================================================ > POST /api/v1/partner/email/configuration-sets/:id/event-destinations — add a webhook URL. # Create event destination Add a webhook destination to a configuration set. Events from sends referencing the config set will be POSTed to your URL with an HMAC-signed body. ```http POST /api/v1/partner/email/configuration-sets/:id/event-destinations ``` ## Request body ```json { "name": "production-webhook", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/email", "webhook_secret": "your-shared-secret-min-16-chars", "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"], "enabled": true } ``` | Field | Type | Required | Notes | |---|---|---|---| | `name` | string | yes | Friendly identifier | | `destination_type` | string | no | `WEBHOOK` only (KAFKA, SNS — roadmap) | | `webhook_url` | string | yes | HTTPS endpoint. Must respond 2xx within 10s | | `webhook_secret` | string | no | HMAC-SHA256 signing key. **Saved write-only** — never echoed back | | `matching_event_types` | string[] | no | Subscribe to specific events. Empty = subscribe to everything | | `enabled` | bool | no | Default `true`. Set `false` to pause without deleting | Valid event types: - `send`, `delivered`, `bounce`, `complaint` - `open`, `click`, `reject` - `rendering_failure`, `delivery_delay` ## Response ```json { "success": true, "destination_id": "ed_550e8400-...", "name": "production-webhook", "webhook_url": "https://yourapp.com/webhooks/email", "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"], "enabled": true } ``` ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_.../event-destinations \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "production-webhook", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/email", "webhook_secret": "...", "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"] }' ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 400 | `INVALID_REQUEST` | Missing `webhook_url` or unknown event type | | 400 | `WEBHOOK_URL_INVALID` | URL must be HTTP(S) | ================================================================================ # Update event destination Section: API Reference › Event Destinations URL: https://email-docs.splashifypro.com/api-reference/event-destinations/update ================================================================================ > PATCH /api/v1/partner/email/configuration-sets/:id/event-destinations/:dest_id # Update event destination Modify a webhook destination — change the URL, rotate the signing secret, narrow/widen subscribed event types, or pause delivery. ```http PATCH /api/v1/partner/email/configuration-sets/:id/event-destinations/:dest_id ``` All fields optional — pass only what's changing. ## Request body ```json { "webhook_url": "https://yourapp.com/v2/webhooks/email", "webhook_secret": "rotated-secret-here", "matching_event_types": ["bounce", "complaint"], "enabled": true } ``` | Field | Type | Notes | |---|---|---| | `name` | string | | | `webhook_url` | string | HTTP(S) only | | `webhook_secret` | string | New value overwrites the old. API never echoes back | | `matching_event_types` | string[] | Replaces the existing list | | `enabled` | bool | Pause/resume delivery | ## Rotating the webhook secret Sequence: 1. Generate a new secret on your side (`openssl rand -hex 32`) 2. Update your endpoint to **accept both old and new** secrets for ~30 seconds 3. PATCH this endpoint with the new secret 4. Wait until in-flight requests drain (~30 seconds) 5. Remove old-secret support from your endpoint We don't echo old-or-new values, so the rotation window has to be coordinated by your code. ## cURL ```bash curl -X PATCH \ https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_.../event-destinations/ed_... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"enabled": false}' ``` ================================================================================ # Delete event destination Section: API Reference › Event Destinations URL: https://email-docs.splashifypro.com/api-reference/event-destinations/delete ================================================================================ > DELETE /api/v1/partner/email/configuration-sets/:id/event-destinations/:dest_id # Delete event destination Removes a webhook destination from a configuration set. Future events for sends through this config set won't fan out to this URL. ```http DELETE /api/v1/partner/email/configuration-sets/:id/event-destinations/:dest_id ``` ## cURL ```bash curl -X DELETE \ https://api.splashifypro.com/api/v1/partner/email/configuration-sets/cs_.../event-destinations/ed_... \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## What this does NOT do - Does NOT replay events your endpoint missed while the destination was misconfigured. Manual replay is on the roadmap. - Does NOT cancel in-flight retries — events that were queued before the delete may still attempt delivery for ~21 minutes (the retry window). ## Pause vs delete If you want to temporarily stop delivery: ```bash curl -X PATCH ... -d '{"enabled": false}' ``` is reversible. Deletion is not — re-creating gives you a fresh `destination_id` and the historical webhook-attempts audit trail no longer matches. ================================================================================ # List suppressed addresses Section: API Reference › Suppression URL: https://email-docs.splashifypro.com/api-reference/suppression/list ================================================================================ > GET /api/v1/partner/email/suppression # List suppressed addresses ```http GET /api/v1/partner/email/suppression ``` ## Query parameters | Field | Type | Notes | |---|---|---| | `reason` | string | `BOUNCE` / `COMPLAINT` / `UNSUBSCRIBE` / `MANUAL` | | `search` | string | Case-insensitive substring match on email | | `limit` | int | 1-1000, default 200 | ## Response ```json { "success": true, "suppression": [ { "email": "deadbox@example.com", "reason": "BOUNCE", "details": "550 5.1.1 user unknown", "added_at": "2026-05-03T11:30:00Z" }, { "email": "spammed@example.com", "reason": "COMPLAINT", "details": "FBL/abuse", "added_at": "2026-05-03T11:35:00Z" } ], "count": 2 } ``` ## cURL ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/suppression?reason=BOUNCE&limit=50' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Get suppression entry Section: API Reference › Suppression URL: https://email-docs.splashifypro.com/api-reference/suppression/get ================================================================================ > GET /api/v1/partner/email/suppression/:email # Get suppression entry ```http GET /api/v1/partner/email/suppression/:email ``` Check whether a specific email is on the suppression list. Useful for pre-flight checks before adding an address to a campaign list. ## Response ```json { "success": true, "entry": { "email": "deadbox@example.com", "reason": "BOUNCE", "details": "550 5.1.1 user unknown", "added_at": "2026-05-03T11:30:00Z" } } ``` ## Common errors | Status | Code | Meaning | |---|---|---| | 404 | `NOT_SUPPRESSED` | The email isn't on the suppression list — safe to send | A 404 here is the **normal "not suppressed" response** — branch on status code, not just body content. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/suppression/deadbox@example.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Put suppression entry Section: API Reference › Suppression URL: https://email-docs.splashifypro.com/api-reference/suppression/put ================================================================================ > PUT /api/v1/partner/email/suppression/:email — add or replace a suppression. # Put suppression entry Idempotent — re-PUTting an existing email overwrites the reason + details with the new values. ```http PUT /api/v1/partner/email/suppression/:email ``` ## Request body ```json { "reason": "MANUAL", "details": "GDPR erasure request 2026-05-03 ticket #1024" } ``` | Field | Type | Required | Notes | |---|---|---|---| | `reason` | string | no | `MANUAL` (default) / `BOUNCE` / `COMPLAINT` / `UNSUBSCRIBE` | | `details` | string | no | Free-text note. Surfaced in audit + UI | ## Response ```json { "success": true, "email": "user@example.com", "reason": "MANUAL" } ``` ## Use cases - **Honoring opt-out clicks in your app** — when a user clicks unsubscribe in your preferences page, push them here so you stop sending across all your sending integrations - **GDPR / DPDP erasure** — adds the address with a `MANUAL` reason + a note referencing the ticket - **Pre-emptive blocklist** — known-bad addresses you never want to email, regardless of the source list ## cURL ```bash curl -X PUT \ https://api.splashifypro.com/api/v1/partner/email/suppression/user@example.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason": "MANUAL", "details": "User unsubscribed via app"}' ``` ================================================================================ # Delete suppression entry Section: API Reference › Suppression URL: https://email-docs.splashifypro.com/api-reference/suppression/delete ================================================================================ > DELETE /api/v1/partner/email/suppression/:email — remove an address from the suppression list. # Delete suppression entry Removes an email from the suppression list, allowing future sends. ```http DELETE /api/v1/partner/email/suppression/:email ``` > **Caution.** If the address bounced hard or complained, removing > it and re-sending is likely to get it suppressed again + drag > down your reputation. Only remove when you have evidence the > underlying cause is fixed (e.g. user changed providers, mailbox > was reactivated). ## cURL ```bash curl -X DELETE \ https://api.splashifypro.com/api/v1/partner/email/suppression/user@example.com \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Response ```json { "success": true } ``` 204 / 404 are both treated as success — if the address wasn't suppressed, the desired end state is already achieved. ================================================================================ # Get quota Section: API Reference › Quotas & Stats URL: https://email-docs.splashifypro.com/api-reference/quotas/get-quota ================================================================================ > GET /api/v1/partner/email/quotas — your daily cap, peak rate, sandbox flag, reputation snapshot. # Get quota Single read-once-per-page summary of your account's sending budget and reputation. ```http GET /api/v1/partner/email/quotas ``` ## Response ```json { "success": true, "quota": { "daily_send_quota": 50000, "peak_send_rate_per_second": 14, "sandbox": false, "sent_today": 1247, "sandbox_free_used_today": 0, "reputation_status": "HEALTHY", "reputation_bounce_rate": 0.0174, "reputation_complaint_rate": 0.0003, "sending_paused": false, "sending_paused_reason": "", "updated_at": "2026-05-03T12:00:00Z" } } ``` | Field | Notes | |---|---| | `daily_send_quota` | Max emails/day (200 in sandbox, 50K in production by default) | | `peak_send_rate_per_second` | Max sends/sec (1 in sandbox, 14 in production) | | `sandbox` | `true` until production access is approved | | `sent_today` | Emails sent today (UTC) | | `sandbox_free_used_today` | Emails consumed against the sandbox free tier | | `reputation_status` | `HEALTHY` / `AT_RISK` / `PAUSED` | | `reputation_bounce_rate` | Rolling 14-day bounce rate (0.0–1.0) | | `reputation_complaint_rate` | Rolling 14-day complaint rate (0.0–1.0) | | `sending_paused` | `true` if account is paused (admin or auto) | ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/quotas \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Bounce report Section: API Reference › Quotas & Stats URL: https://email-docs.splashifypro.com/api-reference/bounce-report ================================================================================ > GET /api/v1/partner/email/bounce-report: bounces by kind and by recipient domain over the last days. # Bounce report Why your emails bounced over the last days: totals, the main kinds of bounce and the recipient domains that bounce most. The same numbers as **Bounce report** in the panel. ```http GET /api/v1/partner/email/bounce-report ``` Connected apps need `email.reports:read`. See [Connected apps (OAuth)](/api-reference/connected-apps). ## Query parameters | Field | Type | Notes | |---|---|---| | `days` | int | 1 to 90, default 30 | ## Response ```json { "success": true, "report": { "sent": 18240, "delivered": 17702, "soft_bounces": 96, "hard_bounces": 214, "hard_bounce_rate": 1.17, "complaints": 6, "opens": 6120, "clicks": 980, "rejected": 22, "by_category": [ { "category": "User not found", "count": 171, "percentage": 55.2, "description": "Recipient mailbox doesn't exist. Remove these addresses from your list." }, { "category": "Mailbox full", "count": 58, "percentage": 18.7, "description": "Recipient mailbox is over quota. Will likely accept mail later." } ], "by_domain": [ { "domain": "example.com", "count": 64, "percentage": 20.6 } ], "window_days": 30 } } ``` | Field | Meaning | |---|---| | `hard_bounces`, `soft_bounces` | Permanent bounces (remove the address) and temporary ones (often accepted later) | | `hard_bounce_rate` | Hard bounces as a percent of `sent`. Keep it low to protect your sending reputation. | | `by_category` | Bounces by kind, most first: `User not found`, `Mailbox full`, `Invalid domain`, `Spam / policy block`, `Connection issues`, `TLS / encryption`, `Others` | | `by_domain` | The 10 recipient domains with the most bounces | | `window_days` | The number of days counted | `by_category` and `by_domain` are empty (or `null`) when nothing bounced. For a file, `GET /api/v1/partner/email/bounce-report.csv` gives the same report as CSV (not open to connected apps). ## cURL ```bash curl "https://api.splashifypro.com/api/v1/partner/email/bounce-report?days=7" \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Common errors | Status | `message` | Why | |---|---|---| | 401 | `unauthorized` | Missing or wrong key or token | | 500 | `database error` | Try again in a moment | ================================================================================ # Get send statistics Section: API Reference › Quotas & Stats URL: https://email-docs.splashifypro.com/api-reference/quotas/get-stats ================================================================================ > GET /api/v1/partner/email/stats — day-by-day send / delivered / bounced / opened / clicked counters. # Get send statistics Day-by-day counters across the rolling window. Account-wide by default; pass `config_set_id` to scope to a specific configuration set. ```http GET /api/v1/partner/email/stats ``` ## Query parameters | Field | Type | Notes | |---|---|---| | `days` | int | 1-90, default 14 | | `config_set_id` | uuid | Scope to one config set instead of account-wide | ## Response ```json { "success": true, "stats": [ { "day_bucket": "2026-05-03", "send_count": 1247, "delivered_count": 1213, "bounced_count": 21, "complained_count": 2, "opened_count": 412, "clicked_count": 87, "rejected_count": 11 }, { "day_bucket": "2026-05-02", "send_count": 1102, ... } ], "days": 14 } ``` Days with zero sends are present in the array (with all counts zero) so you don't have to fill gaps client-side. ## cURL ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/stats?days=30' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Per-config-set: ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/stats?days=14&config_set_id=cs_...' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Get reputation Section: API Reference › Quotas & Stats URL: https://email-docs.splashifypro.com/api-reference/quotas/get-reputation ================================================================================ > GET /api/v1/partner/email/reputation — rolling 14-day bounce + complaint rate. # Get reputation Returns the rolling 14-day bounce + complaint rate plus the classified reputation status. Equivalent to AWS SES `GetAccountReputation`. ```http GET /api/v1/partner/email/reputation ``` ## Response ```json { "success": true, "window_days": 14, "sent": 12500, "bounced": 218, "complained": 4, "bounce_rate": 0.01744, "complaint_rate": 0.00032, "status": "HEALTHY" } ``` ## Status thresholds ``` bounce > 10% OR complaint > 0.5% → PAUSED bounce > 5% OR complaint > 0.1% → AT_RISK else → HEALTHY ``` `PAUSED` triggers automatic sending halt — `/send` returns `403 SENDING_PAUSED`. See [Reputation](/knowledge-base/concepts/reputation) for recovery steps. ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/reputation \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # List events Section: API Reference › Quotas & Stats URL: https://email-docs.splashifypro.com/api-reference/quotas/list-events ================================================================================ > GET /api/v1/partner/email/events — recent event log. # List events Browse the recent event log. Useful for ad-hoc triage when you want to see what's happening without setting up a webhook. ```http GET /api/v1/partner/email/events ``` ## Query parameters | Field | Type | Notes | |---|---|---| | `day_bucket` | string | `YYYY-MM-DD` UTC. Default: today | | `event_type` | string | Filter by event type (lowercase) | | `limit` | int | 1-1000, default 200 | ## Response ```json { "success": true, "events": [ { "event_id": "e_550e8400-...", "event_type": "delivered", "message_id": "550e8400-...", "config_set_id": "cs_...", "recipient": "customer@example.com", "created_at": "2026-05-03T12:34:57Z" }, { "event_id": "e_660e8400-...", "event_type": "bounce", "message_id": "660e8400-...", "recipient": "deadbox@example.com", "bounce_type": "Permanent", "bounce_reason": "no_such_user", "created_at": "2026-05-03T12:35:01Z" }, { "event_id": "e_770e8400-...", "event_type": "click", "message_id": "...", "recipient": "...", "url": "https://yourapp.com/dashboard", "ip": "203.0.113.42", "ua": "Mozilla/5.0 ...", "created_at": "..." } ], "count": 3, "day_bucket": "2026-05-03" } ``` ## cURL ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/events?day_bucket=2026-05-03&event_type=bounce&limit=100' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ## Webhooks vs this endpoint For push-based event delivery, use [webhooks](/webhooks). This endpoint is for ad-hoc reads — debugging, auditing, replaying a window of events into your own database. Note: only the last 30 days of events are retained. For long-term archival, persist them at your end via webhooks. ================================================================================ # Submit production access request Section: API Reference › Production Access URL: https://email-docs.splashifypro.com/api-reference/production-access/submit ================================================================================ > POST /api/v1/partner/email/production-access — request to leave sandbox. # Submit production access request Request your account be moved out of sandbox into full production. Submission triggers an admin review. See [Sandbox vs Production](/knowledge-base/concepts/sandbox) for the review criteria. ```http POST /api/v1/partner/email/production-access ``` ## Request body ```json { "use_case": "We send transactional emails for our SaaS app — signup confirmations, password resets, payment receipts, weekly digest. Recipients are our paying customers who created accounts on our app.", "email_volume_estimate": "5000-15000 per day", "has_unsubscribe_method": true, "has_consent_proof": true } ``` | Field | Type | Required | Notes | |---|---|---|---| | `use_case` | string | yes | ≥30 chars. Real description of WHO you're sending to + WHY they signed up | | `email_volume_estimate` | string | yes | Realistic daily volume | | `has_unsubscribe_method` | bool | yes | Confirms you have unsubscribe links in marketing email | | `has_consent_proof` | bool | yes | Confirms recipients opted in (signup, double-opt-in, purchase, etc.) | | `legal_document` | file | no | Optional supporting document (PDF / PNG / JPEG, max 10 MB). See below | All four data fields are required. Faking them violates AUP — accounts that lie get downgraded. ## Optional legal document attachment You can attach a supporting compliance document — CAN-SPAM attestation, opt-in proof, signed contract, registered-business certificate, etc. — to speed up the review. Submissions that include a relevant document are typically approved faster because the reviewer doesn't need to ask follow-up questions. To attach a document, switch the request from JSON to `multipart/form-data` and include the file under the `legal_document` field. The file is uploaded to our DigitalOcean Spaces bucket and exposed to the admin reviewer via a public URL on the request row. **Limits:** PDF, PNG, or JPEG only. 10 MB max per file. ## Response ```json { "success": true, "request_id": "req_550e8400-...", "status": "PENDING", "domain_verified": true, "message": "Request submitted. Review typically takes 24 business hours.", "legal_document_url": "https://folder.splashifypro.com/partner_email_production_access/...pdf", "legal_document_filename": "compliance-attestation-2026.pdf" } ``` `domain_verified` reflects whether you currently have at least one domain identity in `VERIFIED` status — flagged on the admin side as a "ready for fast approval" signal. `legal_document_url` and `legal_document_filename` are returned only when a document was uploaded with the request. Both fields are omitted otherwise. ## Common errors | Status | Code | Meaning | |---|---|---| | 400 | `USE_CASE_TOO_SHORT` | Description must be ≥30 characters | | 400 | `MISSING_UNSUBSCRIBE_METHOD` | Required for marketing email | | 400 | `MISSING_CONSENT_PROOF` | Recipients must have opted in | | 400 | `INVALID_DOCUMENT_TYPE` | Document must be PDF, PNG, or JPEG | | 400 | `DOCUMENT_TOO_LARGE` | Document must be 10 MB or smaller | | 503 | `UPLOAD_UNAVAILABLE` | Spaces uploader is temporarily down — retry without the file | ## cURL — JSON (no document) ```bash curl https://api.splashifypro.com/api/v1/partner/email/production-access \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "use_case": "...", "email_volume_estimate": "5000 per day", "has_unsubscribe_method": true, "has_consent_proof": true }' ``` ## cURL — multipart with legal document ```bash curl https://api.splashifypro.com/api/v1/partner/email/production-access \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -F "use_case=We send transactional emails for our SaaS app..." \ -F "email_volume_estimate=5000 per day" \ -F "has_unsubscribe_method=true" \ -F "has_consent_proof=true" \ -F "legal_document=@./compliance-attestation.pdf" ``` Note the absence of `Content-Type` — `curl -F` sets the multipart boundary automatically. ================================================================================ # List production access requests Section: API Reference › Production Access URL: https://email-docs.splashifypro.com/api-reference/production-access/list ================================================================================ > GET /api/v1/partner/email/production-access — your submission history. # List production access requests Returns your full history of production-access submissions newest-first. ```http GET /api/v1/partner/email/production-access ``` ## Response ```json { "success": true, "requests": [ { "request_id": "req_550e8400-...", "use_case": "...", "email_volume_estimate": "5000 per day", "has_unsubscribe_method": true, "has_consent_proof": true, "domain_verified": true, "status": "APPROVED", "admin_notes": "Verified domain + clean use case. Approved for production.", "created_at": "2026-05-03T12:00:00Z", "reviewed_at": "2026-05-03T13:30:00Z" } ], "count": 1 } ``` ## Status values | Status | Meaning | |---|---| | `PENDING` | Awaiting review | | `APPROVED` | Lifted out of sandbox + quota raised | | `DENIED` | Resubmit after addressing `admin_notes` | ## cURL ```bash curl https://api.splashifypro.com/api/v1/partner/email/production-access \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` ================================================================================ # Webhooks Section: API Reference › Webhooks URL: https://email-docs.splashifypro.com/webhooks ================================================================================ > Receive real-time events when emails are sent, delivered, bounced, opened, clicked, or replied to. # Webhooks Webhooks let your app react to email lifecycle events as they happen. Send → Delivery → Open → Click → Bounce → Complaint → Reply — every state transition fires an HTTP POST to your URL with a structured JSON payload. ## Two webhook surfaces Pick whichever fits your integration: | Surface | Where you set it | Scope | Best for | |---|---|---|---| | **Account-level webhook** | Settings → Webhook URL in Splashify Pro Email | Every event for every send + lifecycle events (production-access approval, account deletion, etc) | Single endpoint that handles everything; simplest setup | | **Per-config-set destinations** | `POST /partner/email/configuration-sets/:id/event-destinations` | Only events scoped to that config set, filtered by `matching_event_types` | Per-customer or per-product routing; advanced filtering | **You can use both at once.** The account-level URL receives every event regardless of config set; the per-config-set destinations receive their filtered subset additionally. Most customers start with just the account-level URL and add per-config-set destinations later when they need to route per-customer. ## Event types fired to your webhook | Event | When | Surface | |---|---|---| | `email.sent` | Recipient MX accepted the message (250 OK) | both | | `email.delivered` | Same as sent — direct-MX collapses these | both | | `email.bounced` | Hard or soft bounce reported via DSN | both | | `email.complained` | Recipient marked as spam (FBL) | both | | `email.opened` | Recipient opened the email (1×1 pixel loaded) | both | | `email.clicked` | Recipient clicked a link in the email | both | | `email.rejected` | Send refused at the API layer (suppression / quota) | both | | `email.replied` | **Recipient replied to the email** | both | | `production_access.approved` | Admin lifted your sandbox cap | account-level only | | `production_access.denied` | Admin denied your sandbox lift request | account-level only | | `account.deletion.requested` | You requested account deletion | account-level only | | `account.deletion.cancelled` | You cancelled the deletion within the 48h window | account-level only | ## How it works ```mermaid sequenceDiagram participant API as Splashify API participant Worker as Webhook dispatcher participant Hook as Your endpoint API->>Worker: Event recorded Worker->>Worker: Find matching destination
(by config_set + event type) Worker->>Hook: POST signed JSON alt 2xx Worker->>Worker: mark delivered else 5xx / timeout Worker->>Worker: schedule retry
(1m, 5m, 15m) else 4xx Worker->>Worker: gave up
(your URL is broken) end ``` 1. You **create a configuration set** (a logical grouping for sends). 2. You **add a webhook event destination** to that config set, with the URL + secret + the event types you want. 3. You **send emails** with `configuration_set_name` referencing that set. 4. Every event for those sends gets POSTed to your URL with an HMAC-signed body. 5. **Retries:** 5xx + timeout → 1min, 5min, 15min. 4xx → no retry (your URL is broken; we don't waste retries). ## Set up a webhook in 3 calls ### 1. Create a config set ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "production", "suppression_options": "BOUNCE_AND_COMPLAINT" }' ``` Save the `config_set_id` from the response. ### 2. Add a webhook destination ```bash curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets/$CONFIG_SET_ID/event-destinations \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "production-webhook", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/splashify", "webhook_secret": "your-shared-secret-32-chars", "matching_event_types": ["send", "delivered", "bounce", "complaint", "open", "click"] }' ``` > **Security:** Store the `webhook_secret` somewhere your endpoint > can read it (env var). The API will never echo it back — to > rotate, PATCH a new value. ### 3. Reference the config set on send ```bash curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourcompany.com", "to": ["customer@example.com"], "subject": "Welcome", "html_body": "

Hi

", "configuration_set_name": "production" }' ``` Within seconds your endpoint receives a `Send` event, then `Delivery`, etc. ## Payload shape We follow the **AWS SES event-publishing JSON envelope**. Code written against AWS SES SNS subscriptions consumes our webhooks by swapping the auth header verification. ```json { "eventType": "Delivery", "mail": { "timestamp": "2026-05-03T12:34:56Z", "messageId": "550e8400-e29b-41d4-a716-446655440000", "source": "hello@yourcompany.com", "destination": ["customer@example.com"] }, "delivery": { "timestamp": "2026-05-03T12:34:57Z", "recipients": ["customer@example.com"], "smtpResponse": "250 OK" } } ``` Every event has the top-level `eventType` and `mail` fields. The event-specific payload is nested under a key matching the lowercase event type — `delivery`, `bounce`, `complaint`, etc. ## Headers Every POST carries: | Header | Purpose | |---|---| | `Content-Type` | `application/json` | | `User-Agent` | `Splashify-Pro-Webhook/1.0` | | `X-Splashify-Event` | Event type — `Send`, `Delivery`, `Bounce`, ... | | `X-Splashify-Signature` | `sha256=` HMAC-SHA256 of the raw body keyed by your `webhook_secret` | | `X-Splashify-Timestamp` | Unix seconds — protects against replay | | `X-Splashify-Delivery-ID` | UUID per delivery attempt — use for idempotency | ## Quick verify in Node ```js import crypto from "crypto"; app.post("/webhooks/splashify", express.raw({ type: "application/json" }), (req, res) => { const signature = req.header("x-splashify-signature") || ""; const expected = "sha256=" + crypto .createHmac("sha256", process.env.SPLASHIFY_WEBHOOK_SECRET) .update(req.body) .digest("hex"); if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) { return res.status(401).end(); } const event = JSON.parse(req.body.toString()); // process event... res.status(200).end(); }); ``` ## Next - [**Event Types →**](/webhooks/event-types) — full payload shape per event - [**Verify Signature →**](/webhooks/verify-signature) — implementations in 6 languages - [**Retries & Replays →**](/webhooks/retries) — backoff schedule + manual replay - [**Best Practices →**](/webhooks/best-practices) — idempotency, dedup, security ================================================================================ # Event Types Section: API Reference › Webhooks URL: https://email-docs.splashifypro.com/webhooks/event-types ================================================================================ > Every webhook event Splashify Pro fires, with full payload examples. # Event Types The Email API fires nine event types. Subscribe to all of them or just the ones you care about via the `matching_event_types` array on the destination config. | Event | When it fires | Header value | |---|---|---| | [`Send`](#send) | We accept the API call + queue the email | `Send` | | [`Delivery`](#delivery) | Recipient MX returns 250 OK | `Delivery` | | [`Bounce`](#bounce) | Hard or soft bounce | `Bounce` | | [`Complaint`](#complaint) | Recipient marks as spam (FBL report) | `Complaint` | | [`Open`](#open) | Recipient opens the email (pixel loaded) | `Open` | | [`Click`](#click) | Recipient clicks a link in the email | `Click` | | [`Reject`](#reject) | We refused to send (suppression list, etc.) | `Reject` | | [`RenderingFailure`](#renderingfailure) | Template variable substitution failed | `RenderingFailure` | | [`DeliveryDelay`](#deliverydelay) | Soft bounce — will retry | `DeliveryDelay` | Every payload starts with the same envelope: ```json { "eventType": "", "mail": { "timestamp": "ISO8601", "messageId": "uuid", "source": "from-address", "destination": ["to-address"] }, "": { ... } } ``` Below: the event-specific block for each type. ## Send Fires when the API accepts your call. The email is now in the queue — no MX attempt yet. ```json { "eventType": "Send", "mail": { "timestamp": "2026-05-03T12:34:56.123Z", "messageId": "550e8400-e29b-41d4-a716-446655440000", "source": "hello@yourcompany.com", "destination": ["customer@example.com"] }, "send": {} } ``` ## Delivery Fires when the recipient's mailbox provider accepts the email (250 OK). This is the strongest delivery signal — the receiving server has accepted the message for the recipient's mailbox. ```json { "eventType": "Delivery", "mail": { ... }, "delivery": { "timestamp": "2026-05-03T12:34:57.456Z", "recipients": ["customer@example.com"], "smtpResponse": "250 OK" } } ``` ## Bounce Hard bounce (`Permanent`) means the address is dead — recipient is auto-added to your suppression list. Soft bounce (`Transient`) means mailbox-full / server-down / etc. — we retry up to 3 times before giving up. ```json { "eventType": "Bounce", "mail": { ... }, "bounce": { "timestamp": "2026-05-03T12:34:58.789Z", "bounceType": "Permanent", "bounceSubType": "no_such_user", "bouncedRecipients": [ { "emailAddress": "deadbox@example.com", "diagnosticCode": "550 5.1.1 user unknown" } ] } } ``` ## Complaint Recipient marked the email as spam. We received the FBL (feedback- loop) report from their inbox provider and auto-suppressed the address. **Complaints are critical to monitor** — high complaint rates trigger reputation-based sending pauses. ```json { "eventType": "Complaint", "mail": { ... }, "complaint": { "timestamp": "2026-05-03T12:35:10.123Z", "complaintFeedbackType": "abuse", "complainedRecipients": [ { "emailAddress": "customer@example.com" } ] } } ``` ## Open Recipient opened the email — the 1×1 tracking pixel loaded. Privacy- focused mail clients (Apple Mail, etc.) pre-load the pixel proactively, so opens are a directional signal, not an exact one. ```json { "eventType": "Open", "mail": { ... }, "open": { "timestamp": "2026-05-03T12:36:00.000Z", "ipAddress": "203.0.113.42", "userAgent": "Mozilla/5.0 (iPhone; ...)" } } ``` ## Click Recipient clicked a tracked link. We rewrite every `` in the HTML body through a redirect proxy that records the click + 302s to the original URL. Unsubscribe links are NOT tracked. ```json { "eventType": "Click", "mail": { ... }, "click": { "timestamp": "2026-05-03T12:37:00.000Z", "ipAddress": "203.0.113.42", "userAgent": "Mozilla/5.0 (Macintosh; ...)", "link": "https://yourapp.com/dashboard" } } ``` ## Reject We refused to send. Common reasons: recipient on suppression list, sandbox limit reached, sending paused. ```json { "eventType": "Reject", "mail": { ... }, "reject": { "reason": "address on suppression list" } } ``` ## Reply A recipient replied to one of your emails. We catch replies via a unique `Reply-To: reply+@mail.splashifypro.com` we stamp on every outbound (token encodes the original `outbox_id`). When the reply lands at our inbound listener, we parse it, look up which outbound it's responding to, and fire this event. ```json { "eventType": "Reply", "mail": { ... }, "reply": { "outbox_id": "f8c5def1-1234-5678-9abc-def012345678", "original_recipient": "customer@example.com", "from": "Customer Name ", "subject": "Re: Your order has shipped", "message_id": "", "in_reply_to": "", "references": "", "text_body": "Thanks! When can I expect delivery?...", "html_body": "
Thanks! When can I expect...", "received_at": "2026-05-04T09:15:30.123Z" } } ``` `text_body` is truncated to 32 KB and `html_body` to 64 KB — long quoted-thread replies stay inside the webhook envelope without bloating it. Use `in_reply_to` + `references` for thread correlation on your side. **Disabling reply capture.** If you'd rather replies go directly to the address in your `From` header (or your own `Reply-To` if you set one), pass `Reply-To: your-inbox@yourcompany.com` on your send request — when the field is non-empty we won't override it. Replies then route directly to your address and we never see them. > Replies that were already in flight when you change the setting > still arrive at the original `reply+` address until the > recipient updates their thread. ## RenderingFailure Template variable substitution failed — `{{variable}}` referenced in template body wasn't supplied at send time, OR was malformed. ```json { "eventType": "RenderingFailure", "mail": { ... }, "renderingFailure": { "templateName": "welcome", "errorMessage": "missing required variable: first_name" } } ``` ## DeliveryDelay Soft bounce — we'll retry. Fires once on the first retry-eligible soft bounce so you can surface a "delivery delayed" UI without waiting for the final outcome. ```json { "eventType": "DeliveryDelay", "mail": { ... }, "deliveryDelay": { "timestamp": "2026-05-03T12:34:59.000Z", "delayType": "TemporaryFailure", "delayedRecipients": ["customer@example.com"] } } ``` ## Subscribing to a subset Want only bounces and complaints? Set `matching_event_types` on the destination: ```bash curl ... -d '{ "name": "deliverability-alerts", "destination_type": "WEBHOOK", "webhook_url": "https://yourapp.com/webhooks/deliverability", "webhook_secret": "...", "matching_event_types": ["bounce", "complaint"] }' ``` Empty array = subscribe to everything. Specific list = events not on the list are skipped. ## Multiple destinations per config set You can attach multiple webhook destinations to a single config set — one for engagement events (open / click), one for deliverability alerts (bounce / complaint), one for archival (everything). Each destination delivers + retries independently. ================================================================================ # Open & click tracking Section: API Reference › Webhooks URL: https://email-docs.splashifypro.com/webhooks/tracking ================================================================================ > Control which sends generate Open and Click events on your webhook. # Open & click tracking Every email sent through Splashify Pro can carry two kinds of recipient-side instrumentation: | Tracker | Mechanism | Generates | |---|---|---| | **Open** | 1×1 transparent GIF embedded just before `` | `email.opened` event | | **Click** | `` rewriter routing every absolute URL through a redirect proxy | `email.clicked` event | Both are **on by default** on every send (matches AWS SES + Resend + Postmark default). Turn either off when: - You're sending **transactional** mail where engagement metrics aren't useful (password resets, OTP codes, receipts) and the rewritten URLs trip URL-pattern recognition in mail clients. - The recipient population is **privacy-sensitive** (healthcare, legal, financial) and tracking pixels are off-limits per your agreement with them. - You ship **plaintext-only** email — opens require an HTML body to host the pixel; if there's no HTML you'll never see opens regardless of the flag. ## Set defaults per configuration set Tracking flags live on each configuration set, so you can have one config set for marketing (tracked) and another for transactional (untracked): ```bash # Create a config set with tracking ON (default — flags optional) curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "marketing", "track_opens": true, "track_clicks": true }' # Create a config set with tracking OFF — privacy / transactional flow curl https://api.splashifypro.com/api/v1/partner/email/configuration-sets \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "password-reset", "track_opens": false, "track_clicks": false }' ``` Update an existing config set: ```bash curl -X PATCH \ https://api.splashifypro.com/api/v1/partner/email/configuration-sets/$CONFIG_SET_ID \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "track_opens": false }' ``` ## Reference the config set on send ```bash curl https://api.splashifypro.com/api/v1/partner/email/send \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "noreply@yourcompany.com", "to": ["customer@example.com"], "subject": "Your password reset code", "text_body": "Code: 123456", "html_body": "

Code: 123456

", "configuration_set_name": "password-reset" }' ``` The pixel + click rewriter are **skipped** for this send because the config set has both flags off. Recipient sees a clean HTML message without the `/t/o/` pixel or `/t/c/` redirected hrefs. ## Send without a configuration set When you don't pass `configuration_set_name`, both flags default to **true**. To send untracked without setting up a config set, the simplest path is a one-off config set with both off — there's no per-send override flag yet. ## Use your own tracking instead If you have your own analytics (e.g. Plausible, Fathom, an internal warehouse), turn off Splashify tracking on the config set + add your own UTM params or pixel directly inside your HTML body. Splashify won't add a second pixel + won't rewrite your `
` — your links arrive at the recipient verbatim with whatever tracking you embedded. ```html Log in ``` ## What this affects | Surface | With tracking ON | With tracking OFF | |---|---|---| | Recipient HTML | `` rewritten through `/t/c/`; pixel injected before `` | Verbatim HTML, no rewrites | | `email.opened` event | Fires on pixel load | Never fires (no pixel) | | `email.clicked` event | Fires on link click | Never fires (no rewrite) | | `email.sent` / `email.delivered` / `email.bounced` | Fires regardless | Fires regardless | | Bounce / complaint webhooks | Fires regardless | Fires regardless | | Reputation calculation | Unaffected — uses bounce + complaint, not opens / clicks | Unaffected | ## Privacy & compliance notes - **GDPR / DPDP**: tracking pixels can be considered personal data processing. If you operate in jurisdictions requiring explicit consent for tracking, default new senders to a config set with tracking off + opt them in only after consent. - **Apple Mail Privacy Protection (MPP)**: pre-loads pixels on Apple devices, so opens from those clients are inflated. Many customers drop opens entirely + use clicks as the engagement signal. - **Pixel blocking**: Gmail's image proxy serves the pixel from Google's edge — you still get opens but with Google's IP + user agent. Outlook desktop blocks images by default → no open event unless the recipient clicks "show images". ## See also - [Event types →](/webhooks/event-types) — `email.opened` + `email.clicked` + `email.replied` payload details - [Configuration sets →](/api-reference/configuration-sets) — full CRUD reference - [Anti-spam best practices →](/legal/anti-spam) — when tracking helps and when it doesn't ================================================================================ # Verify Signature Section: API Reference › Webhooks URL: https://email-docs.splashifypro.com/webhooks/verify-signature ================================================================================ > Validate webhook authenticity with HMAC-SHA256 in any language. # Verify Signature Every webhook POST carries an `X-Splashify-Signature` header — the HMAC-SHA256 of the **raw request body** keyed by the `webhook_secret` you configured on the destination, hex-encoded with a `sha256=` prefix. > **Verify in constant time.** Standard string equality is > vulnerable to timing attacks. Use your language's > `hmac.compare_digest` / `crypto.timingSafeEqual` / equivalent. ## Node.js ```js import crypto from "crypto"; import express from "express"; const app = express(); // IMPORTANT: read the body as raw bytes, not as parsed JSON, so the // HMAC computation matches what we signed. app.post( "/webhooks/splashify", express.raw({ type: "application/json" }), (req, res) => { const sig = req.header("x-splashify-signature") || ""; const expected = "sha256=" + crypto .createHmac("sha256", process.env.SPLASHIFY_WEBHOOK_SECRET) .update(req.body) .digest("hex"); if (sig.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) { return res.status(401).end(); } const event = JSON.parse(req.body.toString()); handle(event); res.status(200).end(); }, ); ``` ## Python (Flask) ```python import hmac, hashlib, os from flask import Flask, request app = Flask(__name__) SECRET = os.environ["SPLASHIFY_WEBHOOK_SECRET"].encode() @app.post("/webhooks/splashify") def webhook(): sig = request.headers.get("X-Splashify-Signature", "") expected = "sha256=" + hmac.new(SECRET, request.data, hashlib.sha256).hexdigest() if not hmac.compare_digest(sig, expected): return ("", 401) event = request.get_json() handle(event) return ("", 200) ``` ## PHP ```php Result<(), StatusCode> { let sig = headers.get("X-Splashify-Signature") .and_then(|h| h.to_str().ok()).unwrap_or(""); let mut mac = Hmac::::new_from_slice(secret.as_bytes()).unwrap(); mac.update(&body); let expected = format!("sha256={}", hex::encode(mac.finalize().into_bytes())); if !sig.as_bytes().ct_eq(expected.as_bytes()).into() { return Err(StatusCode::UNAUTHORIZED); } // ... handle Ok(()) } ``` ## Common pitfalls - **Don't parse the body before computing HMAC.** Most frameworks parse + serialize JSON, which can change byte-for-byte (whitespace, field order). Always sign the raw bytes you received. - **Constant-time compare.** `==` on strings leaks timing information. Always use the language's secure-compare function. - **Rotation.** When you rotate `webhook_secret` via PATCH, BOTH the old and new value should accept incoming events for ~30 seconds while in-flight requests drain. Implement by storing the previous secret + falling back to it on signature mismatch for a brief window. - **Reject early.** Verify the signature BEFORE any expensive work (DB queries, external calls). Saves resources on forged requests. ## Test fixtures Want to verify your implementation handles a known-good payload? Use this: ``` Body: {"eventType":"Send","mail":{"timestamp":"2026-05-03T12:00:00Z","messageId":"abc","source":"a@b.com","destination":["c@d.com"]},"send":{}} Secret: test-secret Signature: sha256=2bd8e57e9f5b2e8d2f8c4d1c9a1b9c3a3a4f5d6e7c8b9a0d1e2f3a4b5c6d7e8f ``` If your code computes the same hex string, you're verified. ================================================================================ # Retries & Replays Section: API Reference › Webhooks URL: https://email-docs.splashifypro.com/webhooks/retries ================================================================================ > Backoff schedule, retry semantics, and how to manually replay an event. # Retries & Replays The webhook dispatcher retries on transient failures and gives up on permanent ones. This page covers the exact behaviour so your endpoint can plan for it. ## Retry schedule | Attempt | Backoff | When | |---|---|---| | 1 | — | Immediate (within seconds of the event) | | 2 | 1 minute | After attempt 1 fails | | 3 | 5 minutes | After attempt 2 fails | | 4 | 15 minutes | After attempt 3 fails | | Final | give up | After attempt 4 fails — no further retries | Total retry window: ~21 minutes. After that the event is marked `gave_up` in our audit log and no further attempts are made. ## What triggers a retry | Response | Retry? | Reason | |---|---|---| | 2xx (200–299) | No | Delivered | | 3xx | Yes | We don't follow redirects — set up your URL to respond directly | | 4xx (except 408, 429) | **No** | Your endpoint is misconfigured / rejecting; retries waste both sides' budget | | 408 (timeout) | Yes | Treated as transient | | 429 (rate limit) | Yes | Backoff respects `Retry-After` header up to 1 hour | | 5xx | Yes | Transient — recipient claimed the event but couldn't process | | Network timeout | Yes | 10-second timeout per request | ## Why 4xx doesn't retry Most 4xx responses indicate your endpoint is broken in a way time won't fix: - 401/403 — wrong shared secret - 404 — endpoint doesn't exist - 405 — wrong HTTP method - 422 — payload schema mismatch If your endpoint *needs* time to recover (e.g. you just deployed + the route 404s for 30 seconds), respond with `503` instead of `404` during the deploy window. We'll retry. ## Idempotency Every webhook attempt carries a unique `X-Splashify-Delivery-ID` header. Even retries of the same event have a fresh delivery ID. To dedup at your end, key off `mail.messageId` + `eventType`: ```js const key = `${body.mail.messageId}:${body.eventType}`; const inserted = await db.events.insertOne({ _id: key, ...body, receivedAt: new Date(), }, { ignoreDuplicates: true }); if (!inserted.insertedCount) { return res.status(200).end(); // already processed, ack } // ... process ``` The combination is unique per event — even if we retry due to your 500 response, the second delivery has the same `mail.messageId` + `eventType` and your insert dedups it. ## Manual replay For events that gave up (your endpoint was down for >21 minutes), contact support to replay them. We retain the full event log for 30 days and can re-fan-out a specific window. Self-serve replay is on the roadmap — `POST /partner/email/events/replay` with a time range + optional event-type filter. ## Inspecting webhook delivery state To see whether an event was delivered to a destination: ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/events?day_bucket=2026-05-03' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Response includes per-destination delivery status (delivered, failed, gave_up) so you can see which webhooks landed. ## Common reasons for repeated failures - **Endpoint times out > 10 seconds.** Your handler should ack ASAP (write to a queue, return 200) and process async. - **Endpoint behind Cloudflare with bot protection.** Bot challenges return 403 to our requests — whitelist our user-agent (`Splashify-Pro-Webhook/1.0`) or our outbound IP range. - **HTTPS cert expired.** We don't disable cert verification. Renew + monitor. - **Wrong secret.** If you rotated the secret in the panel but didn't roll it on your endpoint, every signature check returns 401. ================================================================================ # Best Practices Section: API Reference › Webhooks URL: https://email-docs.splashifypro.com/webhooks/best-practices ================================================================================ > Production-grade webhook handling — security, idempotency, monitoring. # Webhook Best Practices ## 1. Verify the signature on every request Constant-time HMAC compare. See [Verify Signature](/webhooks/verify-signature) for per-language code. ## 2. Ack fast, process async Your endpoint has 10 seconds before we time out + retry. The retry DOES NOT mean the first call failed — we have no idea until we get a response. Best pattern: ```js app.post("/webhooks/splashify", express.raw({...}), async (req, res) => { // 1. Verify signature // 2. Push to internal queue await queue.push({ rawBody: req.body.toString(), receivedAt: Date.now() }); // 3. Ack immediately res.status(200).end(); }); ``` Process the queue with retries inside your own infrastructure. Your endpoint becomes a fast Layer-7 doorman. ## 3. Dedup by mail.messageId + eventType Retried deliveries have the same logical content but different `X-Splashify-Delivery-ID` headers. Use the body fields as your dedup key: ```js const key = `${body.mail.messageId}:${body.eventType}`; ``` ## 4. Handle out-of-order delivery The dispatcher fans out one POST per (event, destination) combo in parallel — events for the same email may arrive in any order. A `Bounce` event might land before the `Send` event for the same `messageId` if the bounce was inline. Don't assume `Send → Delivery → Open → Click` arrive in order. Drive your state machine off the absolute event types, not their sequence. ## 5. Monitor your endpoint's health Webhook delivery metrics are available via: ```bash curl 'https://api.splashifypro.com/api/v1/partner/email/events?day_bucket=$(date -u +%Y-%m-%d)' \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" ``` Track: - **Delivery rate** — % of events delivered to your endpoint - **Average latency** — `delivered_at - created_at` - **Failed events** — events with `status=failed` or `gave_up` A sudden drop in delivery rate usually means your endpoint started returning 5xx — check your app logs. ## 6. Don't expose your webhook URL publicly The HMAC signature stops forged events, but exposing the URL still attracts unwanted traffic (probes, fuzzing). Guard at the network edge: - Only allow `POST` (not GET / OPTIONS) - Whitelist our outbound IP range if your firewall supports it. IPs are published at [status.splashifypro.com/ip-ranges](https://status.splashifypro.com) and updated when new sending capacity is added — subscribe to the changelog so you don't miss additions. - Reject any request without `X-Splashify-Signature` ## 7. Use one webhook per concern Don't have one giant webhook handler that branches on `eventType`. Have separate config-set destinations for distinct concerns: ``` config_set "production-engagement" → /webhooks/engagement → matching_event_types: ["open", "click"] config_set "production-deliverability" → /webhooks/deliverability → matching_event_types: ["bounce", "complaint", "reject"] config_set "production-archive" → /webhooks/archive → matching_event_types: ["send", "delivered", "bounce", "complaint", "open", "click", "reject"] ``` Smaller handlers = easier to reason about + scope failures. ## 8. Log raw payloads for the first 30 days Keep raw event bodies + headers in your logs (with the `webhook_secret` redacted). When something looks weird, you have the original payload to diff against your handler's behaviour. ## 9. Replay before going to production Use a tool like [Webhook.site](https://webhook.site) to point test sends at — verify your signature check, JSON parsing, and event-type dispatch logic before pointing your real endpoint at us. ## 10. Have a fallback Webhooks can drop. If your business depends on knowing whether an email delivered, periodically poll `/emails/:message_id` for any message you sent in the last hour that hasn't reached a terminal state via webhook. Reconcile the difference. ================================================================================ # Legal & Compliance Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal ================================================================================ > Acceptable use, data processing, service levels, terms, and privacy for the Splashify Pro Email API. # Legal & Compliance This section is the **canonical source** for the legal terms that apply when you use the Splashify Pro Email API. By creating an account or sending a single API request, you agree to everything documented here. ## Quick map | Document | What it covers | |---|---| | [Acceptable Use Policy](/legal/acceptable-use-policy) | What you can and cannot send. Banned content. Banned recipient practices. | | [Auto-Action System](/legal/auto-actions) | Automated thresholds that throttle, pause, or terminate accounts — how they fire, how to recover. | | [Anti-Spam Policy](/legal/anti-spam) | Consent requirements, list-acquisition rules, unsubscribe handling. | | [Data Processing Agreement](/legal/data-processing-agreement) | Controller/processor terms under the DPDP Act 2023 and GDPR. | | [Service Level Agreement](/legal/service-level-agreement) | Uptime targets, support response, service credits. | | [API Terms of Service](/legal/terms-of-service) | The contract between you and us. | | [Privacy Policy](/legal/privacy-policy) | What we collect, why, how long, who we share it with. | | [Compliance Summary](/legal/compliance) | DPDP, GDPR, CAN-SPAM, CASL, ePrivacy at a glance. | | [Incident Response](/legal/incident-response) | Breach notification, abuse reporting, security disclosures. | ## Applicable laws The Splashify Pro Email API operates from India and serves senders worldwide. The following laws apply to your use of the service: - **Information Technology Act, 2000** (India) — electronic records, intermediary liability, reasonable security practices. - **Digital Personal Data Protection Act, 2023** (India, "DPDP Act") — consent, purpose limitation, data principal rights. - **General Data Protection Regulation** (EU GDPR) — when you process personal data of EU/EEA residents. - **CAN-SPAM Act, 2003** (United States) — when sending to US recipients. - **CASL** (Canada) — when sending to Canadian recipients. - **ePrivacy Directive** (EU) — marketing consent and cookie rules. You are responsible for complying with the laws of every country your recipients reside in. Splashify Pro is responsible for operating the sending infrastructure in compliance with Indian law. ## Operator details | Field | Value | |---|---| | Legal entity | EvolvePro Tech Solutions Private Limited | | CIN | U62012WB2025OPC281483 | | GSTIN | 19AAJCE0527G1ZQ | | Registered office | Shimultala, Motiganj, Bongaon, North 24 Parganas, West Bengal — 743235, India | | Grievance Officer | grievance@splashifypro.in | | Data Protection Officer | dpo@splashifypro.in | | Abuse reports | abuse@splashifypro.in | | Security disclosures | security@splashifypro.in | ## Effective date and changes These documents are versioned. The "Effective date" at the top of each page tells you when the current version took effect. We will notify you of material changes at least **30 days** before they take effect via the email address on your account and a banner in Splashify Pro Email. If you disagree with a material change, you may close your account before the change takes effect. Continued use after the effective date constitutes acceptance. ================================================================================ # Acceptable Use Policy Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/acceptable-use-policy ================================================================================ > What you can and cannot send through the Splashify Pro Email API. # Acceptable Use Policy **Effective:** 1 May 2026 This Acceptable Use Policy ("AUP") applies to every email you send through the Splashify Pro Email API. Violations trigger automated enforcement (see [Auto-Action System](/legal/auto-actions)) and may result in account termination and reporting to law-enforcement or internet abuse desks. ## You agree NOT to send ### 1. Illegal content - Content that violates Indian law, including the Information Technology Act, 2000, the Bharatiya Nyaya Sanhita, 2023, the Indecent Representation of Women (Prohibition) Act, the POCSO Act, the Narcotic Drugs and Psychotropic Substances Act, or sectoral regulations issued by SEBI, RBI, IRDAI, or TRAI. - Content that violates the laws of the recipient's country (CAN-SPAM, GDPR, CASL, ePrivacy, etc.). - Defamatory, threatening, or harassing content; doxxing; incitement to violence; revenge porn. ### 2. Sexual content involving minors Content depicting, promoting, or facilitating the sexual exploitation of minors. Such content is reported to the National Cyber Crime Reporting Portal (cybercrime.gov.in) and the National Center for Missing and Exploited Children (NCMEC) without notice to the sender. ### 3. Spam and unsolicited mail - Email to recipients who have not given **clear, affirmative consent** to receive marketing email from your organization. - Email to addresses purchased, rented, scraped, or appended from third-party lists. - Email to addresses harvested from websites, directories, or WHOIS records. - Email to role-based addresses (info@, sales@, postmaster@) without a pre-existing relationship. - Email to disposable / temporary mailbox providers (10minutemail, guerrillamail, mailinator, etc.) with marketing intent. ### 4. Phishing, malware, and fraud - Phishing attempts. Brand impersonation. Credential harvesting. Forged sender identities. - Email containing or linking to malware, ransomware, keyloggers, cryptominers, exploit kits, or malicious browser extensions. - Advance-fee fraud ("Nigerian prince"), romance scams, fake-invoice schemes, business email compromise (BEC). - Pump-and-dump stock promotion. Pyramid schemes. Multi-level marketing where compensation is primarily from recruitment. ### 5. Regulated industries without authorization - Pharmaceuticals, prescription drugs, controlled substances, or recreational drugs. - Tobacco, e-cigarettes, vaping products. Alcohol marketing in jurisdictions where prohibited. - Firearms, ammunition, explosives, weapons of any kind. - Gambling, lottery tickets, or betting services in jurisdictions where unlicensed. - Adult content (pornography, escort services, dating with sexual intent). Splashify Pro does not service this category. - Cryptocurrency or token sales without prior written approval and proof of compliance with SEBI / FIU-IND rules. - Get-rich-quick schemes; "guaranteed income"; binary options; CFDs marketed to retail investors. ### 6. Privacy violations - Sending another person's personal data (PAN, Aadhaar, Voter ID, passport details, bank account numbers, health records) to anyone other than the data principal themselves, without explicit consent and a lawful basis under the DPDP Act 2023. - Doxxing, stalking, or any use of email to facilitate harassment campaigns. ### 7. Deceptive sender behaviour - Forging or misrepresenting the From address, Reply-To address, or any header field. - Routing email through Splashify Pro to bypass another email provider's deliverability filters or suppression list. - Using the API to test, measure, or evade spam filters of major inbox providers (Gmail, Outlook, Yahoo, Apple iCloud, etc.). ### 8. Infrastructure abuse - Reverse-engineering, attacking, or attempting to compromise the API or any internet infrastructure operated by us or any third party. - Sending email designed to trigger automated reply storms (out-of-office loops, vacation responder amplification). - Any activity that degrades the service for other customers. ## Recipient practices we require You must: 1. Honor unsubscribe requests within **10 calendar days**. We process the unsubscribe synchronously when a recipient clicks the link or uses Gmail/Outlook one-click unsubscribe; you must not re-add unsubscribed recipients to your sending list. 2. Maintain proof of consent for each recipient — date, source, wording of the consent prompt — for at least the duration of your sending relationship plus 3 years (DPDP Act §11 record-keeping). 3. Include accurate identification of you as the sender, a valid physical postal address, and a clear unsubscribe link in every marketing email. The Splashify Pro renderer ships these by default in the [Footer block](/api-reference/templates/create); do not strip them in raw-MIME sends. 4. Use a from-domain that you control and that has been [verified through our identity flow](/api-reference/identities/create). 5. Set up SPF, DKIM, and DMARC records for your sending domain. DMARC at `p=quarantine` or `p=reject` is required for production access. 6. Segment marketing and transactional email under separate [configuration sets](/knowledge-base/concepts/configuration-sets) so reputation issues don't bleed across. 7. Suppress hard-bounced and complainted addresses from your sending list immediately. The Splashify Pro suppression list does this automatically; do not work around it. ## Consequences of violation | Severity | Examples | Action | |---|---|---| | Minor | Single deliverability complaint, slightly elevated bounce rate | Email warning + dashboard flag | | Material | Sustained bounce > 5%, complaint > 0.1%, content edge cases | [Auto-pause](/legal/auto-actions) — manual reinstatement | | Severe | Phishing, malware, fraud, CSAM, sustained spam | Immediate termination + report to authorities | The auto-action system runs **without human intervention** and without prior notice on triggered thresholds. See [Auto-Action System](/legal/auto-actions) for the exact thresholds and recovery paths. ## Reporting violations If you believe another sender is abusing the service, email **abuse@splashifypro.in** with the offending message including full headers. We respond to abuse reports within **24 hours** on business days and within 72 hours on weekends. Reports involving CSAM, imminent harm, or active fraud are escalated immediately. ## Updates This AUP may change to reflect new threats or new legal requirements. Material changes get 30 days' notice; clarifications and additions to the banned-content list take effect immediately. Always check the "Effective" date at the top. ================================================================================ # Auto-Action System Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/auto-actions ================================================================================ > Automated thresholds that throttle, pause, or terminate accounts that breach the Acceptable Use Policy. # Auto-Action System **Effective:** 1 May 2026 The Splashify Pro Email API enforces the [Acceptable Use Policy](/legal/acceptable-use-policy) automatically. Thresholds are checked continuously; actions fire **without human intervention** when triggered. This page documents every threshold so you know exactly what happens, why, and how to recover. ## Why we do this automatically A single bad sender hurts every other sender on shared sending infrastructure. Inbox providers (Gmail, Outlook, Yahoo) score the sending domain and IP reputation collectively; one phishing run can trigger blocklisting that affects unrelated customers for days. By acting in seconds rather than waiting for a human review queue, we protect: - **Other customers** from collateral deliverability damage. - **Recipients** from spam, phishing, and fraud. - **Splashify Pro's reputation** as a deliverable email API. ## Reputation thresholds (rolling 14-day window) Every send produces a delivery outcome (sent / delivered / bounced / complained / rejected). We compute the rolling 14-day rate per account and per [configuration set](/knowledge-base/concepts/configuration-sets). | Metric | Healthy | At-risk | Auto-paused | |---|---|---|---| | Bounce rate | ≤ 3% | 3% – 5% | > 5% (or > 10% in any single day) | | Complaint rate | ≤ 0.05% | 0.05% – 0.1% | > 0.1% (or > 0.5% in any single day) | | Spamtrap hits | 0 | 1 | ≥ 2 within 7 days | **At-risk** triggers a warning email and a dashboard banner. Sending continues but at reduced peak rate until the rolling rate falls back to healthy. **Auto-paused** halts every send from the account. New send requests return `403 account_paused` with the reason. The pause is removed only after manual review and remediation — it does not auto-clear. ## Content-based triggers Every outbound message passes through a content classifier before it hits the network. The classifier looks for known phishing kits, malware payload signatures, and the banned categories listed in the [AUP](/legal/acceptable-use-policy). | Trigger | Action | |---|---| | Known phishing kit / brand impersonation | **Block + auto-pause** | | Malware URL / executable attachment | **Block + auto-pause** | | CSAM heuristic | **Block + immediate termination + report** | | Banned regulated category | Block individual send, warn | | URL on Spamhaus DBL / SURBL | Block individual send, warn | The block is reflected in the response: the API returns 200 with `status: "rejected"` and a reason field; the message is never queued. ## Behavioural triggers Some abuse patterns aren't visible from a single message — they only emerge across many. | Pattern | Trigger | Action | |---|---|---| | Recipient list churn | > 50% of recipients are new in a single send batch | At-risk flag + slower send rate | | Disposable mailbox saturation | > 5% of sends to known disposable domains | Block disposable domains, warn | | Hard-bounce ratio on first send to a list | > 15% on first 1,000 messages | Pause batch, warn | | Spamtrap hit | ≥ 1 known spamtrap address in recipient list | Auto-pause | | Repeat AUP violation | Second [AUP](/legal/acceptable-use-policy) breach within 30 days of reinstatement | Termination | ## Sandbox guardrails Every new account starts in **sandbox mode** so first-send mistakes don't damage your reputation. - 200 emails per 24 hours - 1 email per second peak rate - Recipients must be on your verified identity list - `Reply-To` header is automatically set to your registered email so bounces reach you [Request production access](/api-reference/production-access/submit) when you're ready. Approval lifts the sandbox cap; it does not lift the AUP thresholds. ## Recovery paths ### From At-Risk You usually recover automatically when the rolling 14-day rate falls back below the warning threshold. Practical steps: 1. Stop sending to the segment causing bounces or complaints. 2. Clean your list — drop hard bounces (already auto-suppressed), drop addresses that haven't engaged in 90 days, fix any obvious typos. 3. Improve content — clearer From name, accurate subject lines, no misleading preview text. 4. Slow down. New lists should warm up over 7–14 days, not blast all at once. ### From Auto-Paused 1. Identify the cause. The dashboard shows which threshold tripped and a sample of the offending sends. 2. Email **abuse-review@splashifypro.in** with: - Your account ID. - A short explanation of what went wrong. - The remediation steps you've taken (list cleaning, content changes, sending-source segmentation). 3. We review within **2 business days**. If the remediation looks genuine and the violation wasn't deliberate, we lift the pause and place the account on a 30-day probation. A second pause during probation is treated as a [Severe](#severity-levels) violation. ### From Termination Termination is permanent for the account and the legal entity that operated it. Creating a new account to circumvent termination is itself a violation and is detected by our duplicate-detection system (domain + business identifier + payment method overlap). If you believe the termination was an error, email **grievance@splashifypro.in** within **15 days** of termination. We respond within 30 days under the IT (Intermediary Guidelines) Rules. ## Severity levels | Level | Examples | Default action | |---|---|---| | **Minor** | Single user complaint, deliverability blip | Warning email | | **Material** | Sustained reputation breach, AUP edge cases | Auto-pause | | **Severe** | Phishing, malware, fraud, repeated material breaches | Termination | | **Critical** | CSAM, imminent harm, active fraud | Termination + report to authorities | ## Appeal rights You have the right under the IT (Intermediary Guidelines and Digital Media Ethics Code) Rules, 2021 to appeal any account action. Send appeals to **grievance@splashifypro.in**. The Grievance Officer acknowledges within **24 hours** and resolves within **15 days**. If you are dissatisfied with the Grievance Officer's decision, you may escalate to the Grievance Appellate Committee constituted by the Ministry of Electronics and Information Technology under Rule 3A. ## What we never do automatically - Read the body of your emails for any purpose other than the classifier described above. We do not train AI on your content. - Share your sending data with competitors, marketing networks, or any third party who hasn't signed our DPA. - Disclose your sending statistics to your competitors. Reputation data is yours alone. - Modify the body of your emails. We add `List-Unsubscribe` headers and (when requested) tracking pixels — we never rewrite content. ## Transparency Every auto-action writes an entry to your account's audit log. You can [query the audit log via the API](/api-reference/quotas/list-events). We do not delete or modify audit entries; they are append-only and preserved for at least the lifetime of your account plus 3 years (consistent with DPDP Act §11(3) record-keeping). ================================================================================ # Anti-Spam Policy Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/anti-spam ================================================================================ > Consent, list acquisition, unsubscribe handling, and the spam laws we enforce. # Anti-Spam Policy **Effective:** 1 May 2026 Spam isn't just unwelcome — it's illegal in most jurisdictions and damages every legitimate sender on shared sending infrastructure. This page tells you what counts as consent, what list-acquisition practices are forbidden, and how unsubscribes flow through the system. ## What counts as consent You may send marketing email only to recipients who have given **clear, affirmative, recordable consent** to receive marketing email from your specific organization. Consent must: 1. Be **affirmative** — a deliberate action by the recipient (clicked a checkbox, completed a form, sent a written request). Pre-ticked checkboxes do not count. 2. Be **specific** — they consented to email from *your organization*, for *the purpose you'll use it for*. Consent given for "service updates" does not authorize promotional offers. 3. Be **informed** — you told them at the point of consent who you are, what they would receive, and how to withdraw consent. 4. Be **recordable** — you can produce, on request, the date, timestamp, IP address, and exact wording of the consent prompt. Single opt-in is acceptable for most jurisdictions. **Double opt-in (confirmed opt-in)** is required for senders targeting Germany, Austria, Brazil, and is strongly recommended for all sending lists because it cuts complaints and bounces dramatically. ### Consent does NOT include - Membership in a public directory. - Publication of the address on a website. - Provision of the address as part of an unrelated transaction (e.g. someone bought a product — that doesn't authorize marketing unrelated to the purchase). - Forwarded consent ("My friend gave me your email"). - Contractual obligation of the recipient to receive your messages in another channel (e.g. they are your employee or your customer). ### Implied consent (very limited) Some jurisdictions recognize implied consent for transactional or relationship messages. Even where lawful, you should: - Limit messages to the relationship in question (order confirmations, account security alerts, document signings). - Honor unsubscribes the same way you would for marketing. - Refresh consent at least every 24 months. ## Banned list-acquisition practices You must not send through Splashify Pro to addresses obtained through: - **Purchase, rental, or trade** of any list, regardless of the vendor's claims about consent or quality. - **Web scraping** — collecting addresses from websites, social networks, directories, or any place addresses are published. - **Email appending** — taking a name and using a service to "find" the email address. - **Dictionary attacks** — generating addresses by combining names, numbers, or words against a domain. - **Co-registration** — inheriting consent from a partner's signup form unless the partner clearly named your organization at the point of opt-in. - **Contests, sweepstakes, raffles** — unless email consent was a separate opt-in from entering the contest. - **Customer data acquired through merger, acquisition, or bankruptcy** unless consent was specifically transferred to the acquiring entity in the original opt-in language. Sending to any address obtained through the above triggers [Auto-Action System](/legal/auto-actions) responses ranging from auto-pause to termination depending on volume and pattern. ## Unsubscribe requirements ### Every marketing email must include 1. A **functional unsubscribe link** that: - Works without requiring login. - Removes the recipient from your sending list within **10 calendar days** (we do this within seconds). - Does not require entering personal data. - Does not redirect through tracking domains that strip the request. 2. The **`List-Unsubscribe` header** in the format defined by RFC 2369: ``` List-Unsubscribe: , ``` 3. The **`List-Unsubscribe-Post` header** for one-click unsubscribe per RFC 8058, supported by Gmail and Outlook: ``` List-Unsubscribe-Post: List-Unsubscribe=One-Click ``` The Splashify Pro renderer adds all three automatically when you send via `/send`, `/send-template`, or `/send-bulk`. For raw-MIME sends via `/send-raw`, you must include them yourself. ### What unsubscribe means Once a recipient unsubscribes from any of your messages, you may not email that address again from any sending domain you control, regardless of the configuration set or template used. Splashify Pro enforces this account-wide via the [suppression list](/api-reference/suppression/list). ### Re-engagement If an address has unsubscribed from your marketing list, you may not re-add it without **fresh affirmative consent** captured after the unsubscribe. You may continue to send transactional messages (order confirmations, security alerts, legally-mandated notices) to that address. ## Spam laws we enforce Splashify Pro requires you to comply with anti-spam laws of every country your recipients reside in. We particularly check against: ### CAN-SPAM Act, 2003 (US) - Accurate From, Reply-To, and routing information. - Truthful Subject lines. - Identification as an advertisement (where applicable). - A valid physical postal address of the sender. - Functional unsubscribe processed within 10 business days. ### CASL (Canada) - Express consent (verbal recording or written log) for marketing. - Identification of the sender, including any person on whose behalf the message is sent. - Functional unsubscribe processed within 10 business days. - Penalties up to CAD 10 million per violation. ### GDPR (EU) - Lawful basis for processing — typically consent or legitimate interest balanced against the recipient's privacy rights. - Right to object to direct marketing — unsubscribe must be available "by electronic means". - Records of consent must be auditable. ### DPDP Act, 2023 (India) - Notice at the point of collection in the language of the recipient's choice (the 22 official languages of India). - Consent must be free, specific, informed, unconditional, and unambiguous. - Withdrawal of consent must be as easy as giving it. - Penalties up to INR 250 crore. ### ePrivacy Directive (EU) - Requires prior opt-in consent for marketing email to natural persons, even where the underlying GDPR basis would be legitimate interest. ### LGPD (Brazil) - Same consent rigor as GDPR, with explicit prior consent required for marketing in most contexts. ## Spamtrap addresses Spamtraps are addresses planted by inbox providers and reputation services to detect senders who don't have proper consent. They never opt in, so any send to a spamtrap is by definition non-consensual. We auto-detect spamtrap hits via reputation feeds. A single hit produces an auto-pause; two within 7 days is treated as a deliberate list-acquisition violation and may result in termination. The most common cause of spamtrap hits is purchased lists. The second most common is failure to clean a long-dormant list before re-engaging it. Don't do either. ## Engagement-based hygiene Even with proper consent, recipients lose interest. Lists go stale. Bounces and complaints rise. To stay deliverable: - **Monitor engagement.** Open and click rates trending toward zero in a segment is a signal to re-engage or remove. - **Set a freshness threshold.** Drop addresses with no opens or clicks in 12 months. Major inbox providers consider sustained non-engagement a deliverability negative. - **Segment new acquisitions.** Recipients who signed up in the last 30 days behave differently than recipients from 5 years ago. Send them through different [configuration sets](/knowledge-base/concepts/configuration-sets) so reputation issues don't bleed. - **Honor frequency preferences.** If a recipient asks for "monthly only" and you send weekly, you'll see complaints. ## Reporting spam to us If you've received spam from a Splashify Pro sender, forward the message **with full headers preserved** to **abuse@splashifypro.in**. We respond within 24 hours on business days. Acting on abuse reports is mandatory under the IT Act and we take it seriously. ================================================================================ # Data Processing Agreement Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/data-processing-agreement ================================================================================ > Controller / processor terms under the DPDP Act 2023 and the EU GDPR. # Data Processing Agreement **Effective:** 1 May 2026 This Data Processing Agreement ("DPA") forms part of the [API Terms of Service](/legal/terms-of-service) between you (the "Controller" / "Data Fiduciary") and EvolvePro Tech Solutions Private Limited ("Splashify Pro", the "Processor" / "Data Processor"). It applies whenever you use the Splashify Pro Email API to process Personal Data on behalf of yourself or your end-customers. ## 1. Definitions Terms used here have the meanings given in the **Digital Personal Data Protection Act, 2023** (India) ("DPDP") and the **General Data Protection Regulation** (EU) ("GDPR"). Where the two diverge, the more protective definition applies. - **Personal Data** — Information about an identified or identifiable natural person ("Data Principal" / "Data Subject"), including but not limited to email address, IP address, device identifiers, and message content. - **Controller / Data Fiduciary** — The party that determines the purposes and means of processing. - **Processor / Data Processor** — The party that processes Personal Data on behalf of the Controller. - **Sub-processor** — A third party engaged by the Processor to process Personal Data. - **Personal Data Breach** — A breach of security leading to unauthorized access, disclosure, alteration, or destruction of Personal Data. ## 2. Roles For Personal Data sent or processed through the Splashify Pro Email API on your instruction: - **You are the Data Fiduciary / Controller.** You determine which recipients to email, what content to send, and the lawful basis for the processing. - **Splashify Pro is the Data Processor.** We process Personal Data only on your documented instructions, expressed through your use of the API. For Personal Data we collect about you (your account, payment information, usage logs), Splashify Pro acts as the **Data Fiduciary** in its own right; that processing is governed by our [Privacy Policy](/legal/privacy-policy). ## 3. Subject matter and duration | Field | Detail | |---|---| | Subject matter | Sending email on behalf of the Controller | | Duration | Term of the API Terms of Service plus retention periods in §7 | | Nature of processing | Receiving email content + recipient list, signing with DKIM, transmitting via SMTP, storing delivery outcomes | | Purpose | Email transmission and delivery analytics | | Categories of Data | Email addresses, names, IP addresses, message content, headers, delivery metadata | | Categories of Data Principals | Recipients of email sent through the API; senders' employees who configure the account | ## 4. Processor obligations Splashify Pro will: 1. Process Personal Data only on the Controller's documented instructions, including transfers, unless required to do otherwise by Indian or EU law (in which case we will inform the Controller before processing, unless prohibited from doing so). 2. Ensure that personnel authorized to process Personal Data have committed themselves to confidentiality. 3. Implement appropriate technical and organizational measures to ensure a level of security appropriate to the risk, including those listed in §9. 4. Engage Sub-processors only as permitted under §5. 5. Assist the Controller in fulfilling Data Principal rights (access, correction, erasure, portability, objection) within the timeframes set by applicable law. 6. Notify the Controller without undue delay (and within 72 hours) of becoming aware of a Personal Data Breach affecting their data. 7. Make available all information necessary to demonstrate compliance and contribute to audits as set out in §11. 8. Delete or return all Personal Data at the end of the provision of services, except as required to be retained by law. ## 5. Sub-processors Splashify Pro engages the following Sub-processors for the operation of the service. Each is bound by data-protection obligations no less protective than those in this DPA. | Sub-processor | Purpose | Region | |---|---|---| | Cloud infrastructure provider | Compute, storage, networking | India (primary) | | DNS resolution | Delivering email to recipient mail servers | Global anycast | | Inbox feedback loops (Gmail Postmaster, Microsoft SNDS, Yahoo CFL) | Reputation monitoring | US/EU | | Anti-abuse intelligence | Spamtrap, blocklist, malware detection | US/EU | | Payment gateway (Zoho Payments) | Account billing | India | | Telemetry / error monitoring | Service reliability | US (encrypted) | | Customer-support CRM | Handling support tickets | India | We will give the Controller **30 days' prior notice** of changes to the list of Sub-processors. The Controller may object to a change in writing within 15 days; if objection is sustained on legitimate data-protection grounds, the Controller may terminate the relevant service without penalty. ## 6. International transfers Personal Data is primarily stored and processed in India. Some Sub-processors are located outside India. - **DPDP Act:** The Indian government may, by notification, restrict transfers to specified countries. We comply with any such notification. - **GDPR:** Transfers from the EU/EEA to India and to non-adequate jurisdictions are made on the basis of the **Standard Contractual Clauses** (Module 2 — controller to processor) and supplementary measures including encryption in transit and at rest. ## 7. Retention | Data category | Retention | Purpose | |---|---|---| | Email content (body, attachments) | 30 days from send | Bounce diagnosis, support | | Delivery metadata (status, bounce reason, click/open events) | 18 months | Reputation analytics, audit | | Suppression list entries | Indefinite, until removed by Controller | Compliance with §10 of CAN-SPAM and similar laws | | Audit log | Term of agreement + 3 years | DPDP §11(3) record-keeping | | Account billing records | 8 years from invoice | Indian tax law (§44AA Income Tax Act) | On termination, we delete email content and delivery metadata within 30 days. Suppression lists are retained as legal-compliance records unless the Controller specifically requests their deletion. Audit logs and billing records are retained for the legal periods listed above. ## 8. Data Principal rights The Controller is responsible for responding to Data Principal requests. Splashify Pro will assist the Controller through: - API endpoints to query a recipient's status (delivery history, suppression status, click/open events). - Tools to delete a recipient's data on Controller request (`DELETE /suppression/{email}` retains compliance evidence; contact **dpo@splashifypro.in** for full erasure). - Within **48 hours** for requests forwarded to us in writing. ## 9. Security measures Splashify Pro implements security measures appropriate to the risk, including: - **Encryption in transit** — TLS 1.2 or higher for all API calls and SMTP submission to recipient mail servers (with opportunistic STARTTLS where the recipient supports it). - **Encryption at rest** — Storage volumes encrypted with industry-standard algorithms (AES-256 or equivalent). - **Access control** — Role-based access for Splashify Pro personnel; multi-factor authentication; principle of least privilege; audit logging of all administrative access. - **Secure development** — Code review for all changes, automated vulnerability scanning, periodic penetration testing. - **Network controls** — Network segmentation, firewall rules, intrusion detection. - **Backup and recovery** — Encrypted backups with regular restore testing; documented disaster-recovery plan. - **Personnel** — Background checks for all engineers handling production systems; mandatory annual security training. ## 10. Breach notification In the event of a Personal Data Breach affecting Controller data, Splashify Pro will: 1. Notify the Controller **without undue delay and within 72 hours** of becoming aware of the Breach. 2. Provide all reasonable information necessary for the Controller to meet its own notification obligations under DPDP Act §8(6) (notify the Data Protection Board) and GDPR Articles 33 and 34 (notify the supervisory authority and, where required, the Data Subjects). 3. Cooperate with the Controller's investigation and remediation. The notification will include: nature of the Breach, categories and approximate number of Data Principals affected, categories and approximate number of records affected, likely consequences, and measures taken or proposed to address it. ## 11. Audits The Controller may audit Splashify Pro's compliance with this DPA: - By reviewing third-party audit reports (SOC 2, ISO 27001) we publish on request. - By submitting written questions and requesting documentary evidence; we respond within 30 days. - For Controllers processing high volumes of sensitive data, on-site audits can be arranged with 60 days' notice and at the Controller's expense, subject to confidentiality terms and reasonable scope limits. Audit rights do not extend to systems or data of other Controllers. ## 12. Liability Liability for breaches of this DPA is governed by Section 13 of the [API Terms of Service](/legal/terms-of-service). In addition, Splashify Pro indemnifies the Controller for direct losses arising from Splashify Pro's failure to comply with its Processor obligations under DPDP Act §8 and GDPR Article 28, subject to the cap and exclusions in the Terms of Service. ## 13. Termination This DPA terminates automatically on termination of the API Terms of Service. The deletion obligation in §7 survives termination. The audit and breach-notification rights survive for 1 year after termination for events that occurred during the term. ## 14. Order of precedence In case of conflict between this DPA and the API Terms of Service, this DPA prevails for matters of data protection. In case of conflict with mandatory provisions of the DPDP Act or GDPR, the law prevails. ## 15. Governing law This DPA is governed by the laws of India. Disputes are subject to the exclusive jurisdiction of the courts of Kolkata, West Bengal, without prejudice to the Controller's mandatory consumer or data-protection rights under the DPDP Act or GDPR. ## Contact | For | Email | |---|---| | Data-protection enquiries | dpo@splashifypro.in | | Grievance Officer | grievance@splashifypro.in | | Breach notifications | security@splashifypro.in | | Sub-processor change objections | dpo@splashifypro.in | By signing the API Terms of Service or sending your first request, you accept this DPA on behalf of yourself and any end-customer for whom you act. ================================================================================ # Service Level Agreement Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/service-level-agreement ================================================================================ > Uptime targets, support response times, and service credits. # Service Level Agreement **Effective:** 1 May 2026 This Service Level Agreement ("SLA") sets out the availability and support commitments for the Splashify Pro Email API. It applies to production accounts on a paid plan; sandbox and trial accounts are provided on a best-effort basis without SLA commitments. ## 1. Definitions - **Available** — The Email API endpoint at `api.splashifypro.com` accepts a well-formed authenticated request and responds within 30 seconds with HTTP status `2xx` for valid input or appropriate client error (`4xx`) for invalid input. - **Unavailable** — Any 5-minute interval in which the API returns `5xx` errors for more than 50% of valid requests, or fails to respond within 30 seconds for more than 50% of valid requests. - **Monthly Uptime** — `(Total minutes in month - Unavailable minutes) ÷ Total minutes in month`, expressed as a percentage. - **Excluded Downtime** — See §4. ## 2. Uptime commitment | Surface | Monthly Uptime target | |---|---| | Email API (`/partner/email/*`) | **99.95%** | | Webhook delivery (egress) | **99.9%** | | Splashify Pro Email panel (`email.splashifypro.com`) | **99.9%** | | Documentation (`email-docs.splashifypro.com`) | **99.9%** | 99.95% allows for ~22 minutes of unavailability per 30-day month. 99.9% allows for ~43 minutes. Uptime is measured from publicly-reachable monitoring nodes in at least 3 geographic regions (Mumbai, Singapore, Frankfurt). The authoritative measurement is published at [status.splashifypro.com](https://status.splashifypro.com). ## 3. Service credits If we miss the uptime target in a calendar month, you are entitled to service credits applied to the next month's invoice: | Monthly Uptime achieved | Credit | |---|---| | < 99.95% and ≥ 99.9% | 5% of monthly fees for the affected service | | < 99.9% and ≥ 99.0% | 10% | | < 99.0% and ≥ 95.0% | 25% | | < 95.0% | 50% | ### Claiming credits 1. Submit a credit request to **billing@splashifypro.in** within **30 days** of the affected month. 2. Include account ID, the dates and times of the outage you observed, and the impact on your sending. 3. We respond within 10 business days. Credits are applied to the next invoice. They cannot be exchanged for cash and do not roll over more than 12 months. Credits are your **sole and exclusive remedy** for missed uptime targets, except in cases of gross negligence or wilful misconduct. ## 4. Excluded downtime The following do not count against the uptime target: - **Scheduled maintenance** announced at least 7 days in advance via the status page and by email to customers. We schedule maintenance during low-traffic windows where possible. - **Force majeure** events outside our reasonable control — earthquakes, floods, war, terrorism, civil unrest, labor strikes, internet backbone outages, government action. - **Recipient mailbox provider issues** — slow or rejected delivery caused by the recipient's mail server. Webhook events for these outcomes are still delivered. - **Customer-caused outages** — your account paused for AUP violations, missing payment, exhausted wallet, exceeded quotas, or insufficient sender reputation. - **Your network or DNS issues** — failure of your DNS records, your firewall blocking our IPs, or your network infrastructure. - **API misuse** — sending malformed requests, exceeding rate limits, or other behavior counted as `4xx` (which by definition is not an outage on our side). - **Beta features** — anything labelled "Beta" in the documentation. ## 5. Support response times Support is provided in English via email and the in-product chat during Indian business hours (Mon–Sat, 09:30–19:30 IST). | Severity | Definition | First response | Update cadence | |---|---|---|---| | **S1 – Critical** | Production sending blocked, security incident | 1 business hour | Every 2 business hours | | **S2 – High** | Major feature broken, significant deliverability impact | 4 business hours | Every business day | | **S3 – Medium** | Single feature broken, workaround exists | 1 business day | Every 2 business days | | **S4 – Low** | Question, feature request, documentation issue | 2 business days | As needed | S1 issues outside business hours are picked up by the on-call rotation; first response within 4 hours. Severity is set by you when you open the ticket. We may downgrade severity if the issue does not match the definitions above. ## 6. Webhook delivery commitment When a deliverable event (`Send`, `Delivery`, `Bounce`, `Complaint`, `Open`, `Click`, etc.) is generated for a sender that has configured a webhook destination on its [configuration set](/api-reference/configuration-sets/list): - We will attempt delivery to the configured URL. - We will retry on `5xx` and timeout responses according to [our retry schedule](/webhooks/retries). - We will not retry on `2xx` (delivered) or `4xx` (rejected by recipient — assumed to be deliberate). - Webhook backlogs older than **24 hours** that we have failed to deliver after the documented retries are dropped, with audit-log entries you can query. 99.9% target on webhook delivery means we deliver at least 99.9% of generated events within the documented retry window. Events that your endpoint returns `4xx` for are counted as delivered for SLA purposes (we did our part). ## 7. Deliverability We do **not** offer a deliverability SLA. Deliverability depends on your sender reputation, content, list quality, and the policies of recipient mailbox providers — none of which we control. We provide the tooling to maintain good deliverability: [verified identities](/api-reference/identities/list), [suppression list](/api-reference/suppression/list), [reputation monitoring](/api-reference/quotas/get-reputation), [event webhooks](/webhooks/event-types). If you suspect a deliverability issue caused by Splashify Pro infrastructure (e.g. our shared sending IP is on a blocklist), open an S2 ticket and we will investigate. ## 8. Data durability For data we store on your behalf (suppression list, configuration sets, templates, audit log), we target **99.999999999% (11 nines)** durability over a calendar year. We achieve this through replicated storage with periodic backups; no customer action is required. Email **content** in the outbox is retained for 30 days per the [DPA §7](/legal/data-processing-agreement#7-retention) and is not backed up beyond that window. ## 9. Termination for repeated SLA breaches If we miss the monthly uptime target in **3 consecutive months** or in any **5 of 12 rolling months**, you may terminate the affected service at the end of the current billing period without penalty. Pro-rated refund of pre-paid fees is available on request. ## 10. Changes to this SLA We may update this SLA with **60 days' prior notice**. Changes that make the SLA materially less protective give you the right to terminate without penalty within 30 days of the change taking effect. Improvements take effect immediately without notice. ## Status and incident communication | Channel | What it's for | |---|---| | [status.splashifypro.com](https://status.splashifypro.com) | Real-time component status, scheduled maintenance, post-mortems | | Email to account-admin | S1 incidents, scheduled maintenance | | Splashify Pro Email banner | All incidents that affect the panel | | `support@splashifypro.in` | Open a ticket | | `security@splashifypro.in` | Security incidents, breach notifications | ================================================================================ # API Terms of Service Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/terms-of-service ================================================================================ > The contract between you and EvolvePro Tech Solutions Private Limited for use of the Splashify Pro Email API. # API Terms of Service **Effective:** 1 May 2026 These API Terms of Service ("Terms") form a binding contract between you ("you", "your", "Partner") and **EvolvePro Tech Solutions Private Limited** ("Splashify Pro", "we", "us", "our"), CIN U62012WB2025OPC281483, registered at Shimultala, Motiganj, Bongaon, North 24 Parganas, West Bengal — 743235, India. By creating an account, generating an API key, or sending a single request to the Splashify Pro Email API, you agree to these Terms. ## 1. The service The Splashify Pro Email API ("Service") provides programmatic email sending, identity verification, suppression management, and delivery analytics through endpoints documented at **email-docs.splashifypro.com**. ## 2. Eligibility You may use the Service only if: - You are at least 18 years old. - You have the legal authority to enter into this agreement on behalf of yourself or the entity you represent. - You are not located in, ordinarily resident in, or organized under the laws of a country subject to comprehensive Indian or US trade sanctions. - You have not previously been terminated by us for breach. ## 3. Account registration You will provide accurate, current, complete information during registration and keep it up to date. You are responsible for safeguarding your API keys and for all activity under your account. Notify **security@splashifypro.in** immediately if you suspect unauthorized access. You are responsible for the actions of every team member or end user you grant access to. ## 4. Acceptable use You must comply with the [Acceptable Use Policy](/legal/acceptable-use-policy) and the [Anti-Spam Policy](/legal/anti-spam) at all times. Breach triggers the [Auto-Action System](/legal/auto-actions) and may result in account termination. ## 5. Fees and payment ### 5.1 Pricing Email sending is billed at **₹0.03 per message**, with the first **200 emails per 24 hours free** while in sandbox. Production accounts pay the per-email rate plus any minimum-commit pricing in your order form. Pricing is in Indian Rupees (INR) and exclusive of GST and other applicable taxes. ### 5.2 Wallet model Production accounts maintain a prepaid wallet balance. Sends are deducted from the wallet at the time of acceptance. Insufficient wallet balance results in send rejection until the wallet is topped up. Wallet recharges are processed via Zoho Payments and a tax invoice is issued automatically. GST is applied at the rate prescribed by Indian tax law (currently 18% IGST or CGST+SGST). ### 5.3 Refunds Wallet balance refunds are governed by the [Refund Policy](https://splashifypro.com/refund-policy). In summary: - Used balance is non-refundable. - Unused balance can be refunded on account closure, less applicable GST, within 7 working days. - Per-email charges that fail due to verifiable Splashify Pro infrastructure issues are credited back automatically. ### 5.4 Late payment Invoices issued for post-paid services are due within 30 days. Late payment accrues interest at 1.5% per month (18% per annum). We may suspend the Service after 60 days' overdue and terminate after 90 days. ### 5.5 Taxes You are responsible for all taxes assessed on your use of the Service except taxes on our income. For Indian customers, GST is included on every invoice; for foreign customers, the export of service is zero-rated under Indian GST law. ## 6. Your data You retain all rights, title, and interest in the data you send through the Service ("Customer Data"), including email content, recipient lists, and template content. You grant us a limited, worldwide, royalty-free license to process Customer Data solely for the purpose of operating the Service — delivering email, generating delivery analytics, providing support, detecting abuse, and complying with law. The processing of Customer Data is governed by the [Data Processing Agreement](/legal/data-processing-agreement). ## 7. Our intellectual property We retain all rights, title, and interest in the Service, including the API, documentation, software, designs, trademarks, and copyrighted material. You receive a limited, non-exclusive, non-transferable, revocable license to use the Service per these Terms. You may not: - Reverse-engineer, decompile, or attempt to derive the source code of any part of the Service except as permitted by mandatory law. - Remove or alter our trademarks, copyright notices, or attribution. - Use the Service to build a competing service. - Use scraping, mass-extraction, or "scraper" tools against any endpoint. ## 8. Confidentiality Each party will protect the other's confidential information using the same care it uses for its own (and at least reasonable care). Confidential information includes pricing, technical specifications, and any information marked or reasonably understood as confidential. Our system telemetry, internal architecture, and operational details are confidential to us. ## 9. Service Level Agreement We commit to the uptime and support response times in the [Service Level Agreement](/legal/service-level-agreement). Service credits are your sole remedy for missed uptime targets. ## 10. Suspension and termination ### 10.1 By you You may cancel your account at any time via the Splashify Pro Email panel or by emailing **support@splashifypro.in**. Cancellation takes effect at the end of the current billing period. Unused wallet balance is refunded per §5.3. ### 10.2 By us We may suspend or terminate your account immediately, without notice, if: - You materially breach these Terms or any of the linked policies. - The [Auto-Action System](/legal/auto-actions) detects severe abuse. - Required by law or court order. - Your account becomes inactive for 12 consecutive months and has zero wallet balance. For non-severe breaches, we will give you a 7-day cure period if remediation is feasible. We may also terminate for convenience with **90 days' written notice**. ### 10.3 Effect of termination On termination: - Your access to the API is revoked immediately. - We delete email content and delivery metadata per the retention schedule in the [DPA §7](/legal/data-processing-agreement#7-retention). - Suppression-list entries are retained per legal obligation. - Outstanding invoices remain due. Pre-paid wallet balance is refunded per §5.3 unless termination was for severe breach (in which case it may be retained to cover damages). - Sections 5 (for unpaid amounts), 6, 7, 8, 11, 12, 13, 14, 15, and 16 survive termination. ## 11. Warranties and disclaimers You warrant that: - You have all rights and consents necessary for the email content and recipient lists you send through the Service. - You will comply with all applicable laws. - You will not use the Service to send the content prohibited by the AUP. The Service is provided **"as is" and "as available"**. We disclaim all implied warranties to the maximum extent permitted by law, including implied warranties of merchantability, fitness for a particular purpose, non-infringement, and any warranties arising from a course of dealing or usage of trade. We do not warrant that the Service will be uninterrupted or error-free or that any particular email will be delivered to a recipient's inbox. ## 12. Indemnity You will defend, indemnify, and hold harmless Splashify Pro and its officers, directors, employees, and Sub-processors from and against all third-party claims, damages, liabilities, settlements, and expenses (including reasonable attorneys' fees) arising out of or related to: - Your breach of the AUP, Anti-Spam Policy, or these Terms. - Customer Data, including claims that it infringes third-party rights or violates law. - Your products or services. We will defend you against any claim by a third party that your authorized use of the Service infringes that party's copyright, trade secret, or registered Indian patent, subject to the cap in §13. ## 13. Limitation of liability To the maximum extent permitted by law: - Neither party will be liable for indirect, incidental, special, consequential, exemplary, or punitive damages, or for lost profits, lost revenue, lost data, or business interruption, arising out of these Terms, even if advised of the possibility. - Each party's total cumulative liability arising out of or related to these Terms is capped at the **fees paid to Splashify Pro by you in the 12 months preceding the claim**. - The cap does **not** apply to: (a) your obligations under §5 (Fees), (b) your indemnity under §12, (c) breach of confidentiality under §8, (d) infringement of the other party's intellectual property, (e) gross negligence or wilful misconduct, (f) statutory liabilities that cannot be limited by contract under Indian or EU data-protection law. ## 14. Force majeure Neither party is liable for delay or failure caused by events outside its reasonable control, including acts of God, government action, war, terrorism, riots, internet backbone failures, or recipient mailbox provider blocking. The affected party will resume performance as soon as reasonably practicable. ## 15. Governing law and dispute resolution These Terms are governed by the laws of India. Disputes will first be referred to good-faith negotiation between designated representatives of each party for **30 days**. If unresolved, disputes will be referred to **mediation** under the Mediation Act, 2023 conducted by a sole mediator agreed by the parties or, failing agreement, appointed by the Indian Council for Mediation. If mediation fails, disputes will be finally resolved by **arbitration** in **Kolkata, West Bengal** under the Arbitration and Conciliation Act, 1996, by a sole arbitrator agreed by the parties or appointed by the Calcutta High Court. The seat is Kolkata; the language is English. The arbitral award is final and binding. The courts of Kolkata have exclusive jurisdiction for matters not subject to arbitration (including interim relief). Nothing prevents either party from seeking equitable relief in any court of competent jurisdiction to protect intellectual property or confidential information. ## 16. General - **Notices.** Notices to you may be given by email to your account email or by posting in the Splashify Pro Email panel. Notices to us must be sent to **legal@splashifypro.in** with a copy to our registered office address. - **Assignment.** You may not assign these Terms without our prior written consent. We may assign these Terms in connection with a merger, acquisition, or sale of substantially all of our assets, on notice to you. - **Entire agreement.** These Terms, the linked policies, and any signed order form constitute the entire agreement between the parties. They supersede all prior agreements. - **No partnership.** Nothing in these Terms creates a partnership, joint venture, agency, or employment relationship. - **Severability.** If any provision is held unenforceable, the remainder continues in full effect. - **No waiver.** Failure to enforce a provision is not a waiver. - **Modifications.** We may update these Terms with 30 days' notice for material changes; updates for clarity or new features take effect immediately. Continued use after the effective date is acceptance. - **Headings.** Headings are for convenience only. - **Counterparts and electronic acceptance.** These Terms may be accepted electronically. An electronic acceptance has the same effect as a wet-ink signature under the IT Act, 2000. ## Contact | For | Email | |---|---| | Sales / contracts | sales@splashifypro.in | | Support | support@splashifypro.in | | Billing | billing@splashifypro.in | | Legal | legal@splashifypro.in | | Grievance Officer | grievance@splashifypro.in | | Data Protection Officer | dpo@splashifypro.in | | Abuse | abuse@splashifypro.in | | Security | security@splashifypro.in | ================================================================================ # Privacy Policy Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/privacy-policy ================================================================================ > How Splashify Pro collects, uses, and protects information about customers using the Email API. # Privacy Policy **Effective:** 1 May 2026 This Privacy Policy explains how **EvolvePro Tech Solutions Private Limited** ("Splashify Pro", "we", "us") handles personal information about customers using the Splashify Pro Email API and the Splashify Pro Email panel at email.splashifypro.com. This policy covers personal information about **you** (the customer). For information about how we process **email recipient** data on your behalf, see the [Data Processing Agreement](/legal/data-processing-agreement). ## 1. Who we are Splashify Pro is a brand of EvolvePro Tech Solutions Private Limited, a company incorporated in India (CIN U62012WB2025OPC281483, GSTIN 19AAJCE0527G1ZQ), with registered office at Shimultala, Motiganj, Bongaon, North 24 Parganas, West Bengal — 743235, India. For customer-account data we are the **Data Fiduciary** (DPDP Act terminology) / **Controller** (GDPR terminology). ## 2. What we collect about you | Category | Examples | Source | |---|---|---| | Account identifiers | Name, email, mobile number, business name, GSTIN, address | You, at signup or in /billing | | Authentication | Hashed password, OTP codes, JWT session, two-factor settings | You, at signup or login | | Billing | Invoice details, payment instrument tokens (we never store card numbers), GST treatment | You + Zoho Payments | | Usage data | API requests, IP address, user-agent, timestamps, error responses | Automatic from API and panel | | Account telemetry | Wallet balance, send volume, reputation score, configuration sets created | Automatic | | Support records | Tickets, chat transcripts, screenshots you provide | You, when contacting support | We do **not** intentionally collect special-category data about you (health, biometric, religious, etc.). If you provide such data voluntarily (e.g. in a support message), we minimize handling and delete it as soon as the support issue is resolved. ## 3. Why we use it We process your information for the following purposes, with the lawful basis under Indian and EU law: | Purpose | DPDP basis | GDPR basis | |---|---|---| | Provide and operate the Service | Performance of contract | Article 6(1)(b) | | Bill you and collect payment | Performance of contract | Article 6(1)(b) | | Detect and prevent abuse, fraud, and AUP violations | Legitimate use; legal obligation | Article 6(1)(f); 6(1)(c) | | Comply with tax, accounting, anti-money-laundering, and IT Act obligations | Legal obligation | Article 6(1)(c) | | Deliver service notifications and incident alerts | Performance of contract | Article 6(1)(b) | | Send product updates, newsletters, and marketing | Consent | Article 6(1)(a) | | Improve the Service through aggregated analytics | Legitimate use | Article 6(1)(f) | | Defend ourselves in legal proceedings | Legitimate use; legal obligation | Article 6(1)(f); 6(1)(c) | You can withdraw consent for marketing at any time from the Splashify Pro Email panel or by clicking unsubscribe. ## 4. Who we share it with We share your information only with: - **Sub-processors** listed in the [DPA §5](/legal/data-processing-agreement#5-sub-processors). They process data on our instructions and under contracts that mirror this policy. - **Tax authorities** (GST, Income Tax, etc.) when required by law. - **Law-enforcement and regulators** in response to lawful requests (search warrants, court orders, etc.). We require valid legal process; we challenge overbroad requests where appropriate. - **Acquirers** in the event of a merger, acquisition, or sale of assets, subject to a confidentiality undertaking. - **Other customers on shared sending infrastructure**: only reputation-affecting metadata (suppression list entries are account-private; reputation scores are aggregated such that no single customer is identifiable). We do **not** sell your personal information. ## 5. International transfers We are headquartered in India and primary storage is in India. Some Sub-processors are located outside India (analytics, error monitoring). For transfers from the EU/EEA, we rely on Standard Contractual Clauses with supplementary measures. For DPDP Act compliance, we comply with any government notifications restricting transfers to specific jurisdictions. ## 6. Retention | Category | Retention | |---|---| | Account profile | Term of agreement + 3 years (DPDP §11(3)) | | Billing and tax records | 8 years (Income Tax Act) | | Authentication logs | 12 months | | Support records | 5 years | | Marketing-consent records | Until consent withdrawn + 3 years | | Aggregated analytics | Indefinite (no longer personally identifiable) | After retention periods expire, we delete personal data in a documented, audited process. Backup copies cycle out within 90 days. ## 7. Your rights Under the **DPDP Act, 2023**, you have the right to: - **Access** the personal data we hold about you and the names of Data Processors we have shared it with. - **Correct** inaccurate or incomplete data. - **Erase** data we no longer have a lawful basis to keep. - **Withdraw consent** for any processing we rely on consent for. - **Nominate** another person to exercise your rights in case of death or incapacity. - **Grievance redressal** — escalate through our Grievance Officer to the Data Protection Board of India. Under the **EU GDPR**, you additionally have the right to: - **Data portability** — receive a copy in machine-readable format. - **Object** to processing based on legitimate interest. - **Lodge a complaint** with your supervisory authority (e.g. CNIL, ICO, Garante). To exercise rights, email **dpo@splashifypro.in**. We respond within **30 days** (DPDP) or **1 month, extendable by 2 months for complex requests** (GDPR), at no cost. We may need to verify your identity. ## 8. Cookies and tracking The Splashify Pro Email panel uses: - **Strictly necessary cookies** — session, CSRF token, login state. These are not subject to consent. - **Functional cookies** — UI preferences. Set on first interaction. - **Analytics** — aggregated usage to improve the panel. We do not use third-party advertising trackers in the Splashify Pro Email panel. You can manage cookies via your browser settings. Disabling strictly necessary cookies will prevent the panel from working. The marketing site (splashifypro.com) uses additional analytics and advertising trackers; see the [marketing-site Privacy Policy](https://splashifypro.com/privacy-policy) for details. ## 9. Security See [DPA §9](/legal/data-processing-agreement#9-security-measures) for the technical and organizational measures we implement. In summary: encryption in transit and at rest, role-based access control, multi-factor authentication for staff, secure development practices, periodic penetration testing, and incident response. No system is perfectly secure. If you suspect a security issue, email **security@splashifypro.in**. ## 10. Children The Service is for businesses and not directed at individuals under 18. We do not knowingly collect data from minors. If you believe a minor has provided data, email **dpo@splashifypro.in** and we will delete it. ## 11. Automated decision-making The [Auto-Action System](/legal/auto-actions) automatically restricts or pauses accounts that breach reputation or AUP thresholds. These decisions are based on objective metrics (bounce rate, complaint rate, content classifier output) and are reviewable on appeal. The system does not profile customers for any purpose other than preventing service abuse. ## 12. Marketing We may use your account email to send: - **Service notifications** (incidents, scheduled maintenance, product updates) — you cannot opt out as long as you have an active account. - **Marketing emails** about new features, integrations, and offers — opt-in only at signup; unsubscribe anytime. We will never sell your contact details to third parties for marketing. ## 13. Grievance redressal Under Rule 3 of the IT (Intermediary Guidelines and Digital Media Ethics Code) Rules, 2021, we have appointed a Grievance Officer: - **Name:** Grievance Officer, Splashify Pro - **Email:** grievance@splashifypro.in - **Address:** Shimultala, Motiganj, Bongaon, North 24 Parganas, West Bengal — 743235, India The Grievance Officer acknowledges complaints within **24 hours** and resolves within **15 days**. If you are dissatisfied with the Grievance Officer's decision, you may escalate to the **Grievance Appellate Committee** under Rule 3A. ## 14. Changes We may update this Privacy Policy. We will notify you of material changes via email and a banner in the Splashify Pro Email panel at least **30 days** before the change takes effect. Continued use after the effective date is acceptance. ## 15. Contact | For | Email | |---|---| | Privacy questions, rights requests | dpo@splashifypro.in | | Grievance redressal | grievance@splashifypro.in | | Security incidents | security@splashifypro.in | | Account or billing | support@splashifypro.in | Postal address: Shimultala, Motiganj, Bongaon, North 24 Parganas, West Bengal — 743235, India. ================================================================================ # Compliance Summary Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/compliance ================================================================================ > DPDP Act, IT Act, GDPR, CAN-SPAM, CASL, ePrivacy at a glance. # Compliance Summary **Effective:** 1 May 2026 This page summarizes the major laws and standards that apply when you use the Splashify Pro Email API. It is **informational** — it is not a substitute for legal advice from a lawyer qualified in your jurisdiction. The full obligations are documented in the [API Terms of Service](/legal/terms-of-service), [Acceptable Use Policy](/legal/acceptable-use-policy), [Anti-Spam Policy](/legal/anti-spam), [Data Processing Agreement](/legal/data-processing-agreement), and [Privacy Policy](/legal/privacy-policy). ## India ### Information Technology Act, 2000 The IT Act governs electronic records, intermediary liability, and reasonable security practices. **Our compliance:** - We operate as an "intermediary" under §2(1)(w) and observe intermediary due diligence under Rule 3 of the IT (Intermediary Guidelines and Digital Media Ethics Code) Rules, 2021. - We have appointed a [Grievance Officer](/legal/privacy-policy#13-grievance-redressal) with public contact details. - Reasonable security practices implemented per §43A and ISO 27001- aligned controls. - Take-down on receipt of court order or government notification per §69A and Rule 3(1)(d). **Your obligation:** Don't send content prohibited by §66, §67, §69 of the IT Act (impersonation, obscenity, defamation, hate speech). ### Digital Personal Data Protection Act, 2023 India's first comprehensive privacy law. Key concepts: - **Data Fiduciary** — you, when sending to your end-customers. - **Data Processor** — Splashify Pro, processing recipient data on your instructions. - **Data Principal** — the recipient (or you, when we hold your account data). **Key obligations on you (Data Fiduciary):** | Obligation | What it means for email senders | |---|---| | Lawful purpose (§4) | Only send for a lawful purpose with a valid lawful basis | | Notice (§5) | Tell recipients what data you collect, for what purpose, and how to withdraw consent — at the point of collection, in their preferred language | | Consent (§6) | Free, specific, informed, unconditional, unambiguous; clear affirmative action | | Withdrawal (§6(4)) | As easy to withdraw as to give | | Purpose limitation (§7) | Don't repurpose data without fresh consent | | Storage limitation (§8(7)) | Delete when purpose is fulfilled | | Data Principal rights (§11–13) | Honor access, correction, erasure, grievance | | Breach notification (§8(6)) | Notify Data Protection Board "without delay" | | Children (§9) | Don't process personal data of minors without parental consent; no behavioral monitoring | **Significant Data Fiduciaries** (designated by the Central Government for high-volume or sensitive processing) have additional obligations including a Data Protection Officer, audits, and DPIA. We act as DPF and meet those requirements; you should evaluate whether you do too. **Penalties:** Up to **INR 250 crore** per violation. ### Telecom Commercial Communications Customer Preference Regulations, 2018 (TRAI) Primarily targets SMS and voice but referenced in connection with unsolicited commercial communications. Email is largely governed by the IT Act and DPDP. Senders should observe DND (Do Not Disturb) preferences on multi-channel campaigns. ### Income Tax Act, 1961 — Record retention We retain billing records for 8 years per §44AA. Tax invoices issued through Zoho Payments include GSTIN and HSN/SAC codes per GST law. ## European Union / EEA ### General Data Protection Regulation (GDPR) — Regulation 2016/679 Applies to processing of personal data of EU/EEA residents, regardless of where the processor is located. **Roles:** You are the **Controller**; Splashify Pro is the **Processor**. The [DPA](/legal/data-processing-agreement) is the Article 28 written contract. **Key obligations on you (Controller):** - Lawful basis (Article 6) — for marketing email, this is typically consent (Article 6(1)(a)) or legitimate interest (Article 6(1)(f)) balanced against the recipient's privacy rights. - Information at collection (Articles 13–14). - Purpose limitation, data minimization, storage limitation (Article 5). - Records of processing (Article 30). - Data Subject rights (Articles 15–22). - Breach notification within 72 hours (Article 33). - Data Protection Impact Assessment for high-risk processing (Article 35). - Lawful international transfers (Articles 44–49). **Penalties:** Up to **EUR 20 million or 4% of global annual turnover**, whichever is higher. ### ePrivacy Directive — 2002/58/EC (as amended) Requires **prior opt-in consent** for direct marketing email to natural persons in the EU/EEA, even where GDPR would allow legitimate interest. Limited "soft opt-in" exception for similar products to existing customers (Article 13(2)) with each message offering an unsubscribe. ### LGPD (Brazil) — Lei Geral de Proteção de Dados Pessoais GDPR-aligned. Same consent rigor and rights. We comply for transfers involving Brazilian residents. ## United States ### CAN-SPAM Act, 2003 Federal law. Applies to commercial email sent to US recipients. **Key obligations:** - Accurate From, Reply-To, and routing information. - Truthful Subject lines. - Identification as advertisement (where applicable). - Valid physical postal address of the sender. - Functional unsubscribe processed within 10 business days. **Penalties:** Up to **USD 50,120 per email** under FTC enforcement. ### State laws California (CCPA/CPRA), Virginia (VCDPA), Colorado (CPA), and other state privacy laws may impose additional requirements depending on the recipients you target. ### TCPA — Telephone Consumer Protection Act Primarily covers calls and SMS, but cited in unsolicited-message litigation. Email senders should be aware in case of mixed-channel campaigns. ## Canada ### CASL — Canada's Anti-Spam Law Among the strictest anti-spam laws globally. **Key obligations:** - **Express consent** (verbal recording or written log) for marketing. - Identification of the sender, including any person on whose behalf the message is sent. - Functional unsubscribe processed within 10 business days. **Penalties:** Up to **CAD 10 million per violation**. ## Other notable jurisdictions | Country | Key law | Notes | |---|---|---| | UK | UK GDPR + Data Protection Act 2018 | Substantially aligned with EU GDPR post-Brexit | | Australia | Spam Act 2003 + Privacy Act 1988 | Express, inferred, or implied consent | | Singapore | PDPA 2012 + Spam Control Act 2007 | Opt-in / opt-out hybrid | | UAE | PDPL 2021 | GDPR-aligned, UAE-specific bases | | Switzerland | revFADP 2023 | GDPR-aligned | ## Standards and certifications We work toward and align with: - **ISO 27001** (Information Security Management System) — design aligned; certification roadmap on the trust portal. - **SOC 2 Type 2** — audit roadmap on the trust portal. - **PCI DSS** — payment processing is delegated to Zoho Payments (PCI Level 1); we never store cardholder data. Trust portal: **trust.splashifypro.com** (forthcoming). ## What this means in practice If you are sending email through Splashify Pro: 1. Have a **lawful basis** for every recipient on your list. For most, that's clear affirmative consent. 2. Maintain a **record** of consent — what was said, when, from where. 3. Include in every marketing email: accurate sender identity, a valid physical address, a functional unsubscribe link. 4. Honor unsubscribes **immediately** (we do this within seconds). 5. Don't use the API for content prohibited by the [Acceptable Use Policy](/legal/acceptable-use-policy). 6. If you experience a data breach involving recipient data, notify us at **security@splashifypro.in** within 24 hours so we can support you in the breach-notification timeline. ## Get help For specific compliance questions, consult a lawyer in the relevant jurisdiction. For Splashify Pro's compliance posture, email **legal@splashifypro.in**. For data-protection enquiries, email **dpo@splashifypro.in**. ================================================================================ # Incident Response Section: Legal › Legal URL: https://email-docs.splashifypro.com/legal/incident-response ================================================================================ > Reporting security incidents, abuse, and data breaches. # Incident Response **Effective:** 1 May 2026 This page tells you how to report security issues, abuse, and data incidents — and what to expect from us when you do. ## Quick reference | Type of report | Email | Response time | |---|---|---| | Security vulnerability in our service | security@splashifypro.in | 24 hours | | Suspected breach of recipient data | security@splashifypro.in | 24 hours / 72 hours formal | | Spam, phishing, or abuse from a Splashify Pro sender | abuse@splashifypro.in | 24 hours business / 72 hours weekend | | Privacy / data-protection issue | dpo@splashifypro.in | 30 days statutory | | Grievance redressal | grievance@splashifypro.in | 24 hours acknowledge / 15 days resolve | | Suspected unauthorized access to **your** account | security@splashifypro.in + lock immediately | Immediate | ## Reporting a security vulnerability We welcome reports from security researchers. To report: 1. Email **security@splashifypro.in** with: - Steps to reproduce. - Expected vs actual behavior. - Impact assessment (what could an attacker do?). - Your name and contact details (or pseudonym if you prefer). 2. Encrypt sensitive details with our PGP key (published on the trust portal). For most reports, plain email is fine. 3. Do **not** publicly disclose until we have had a reasonable chance to investigate and fix. ### Our commitments - We acknowledge within 24 hours. - We provide a tracking ID and a single point of contact. - We share periodic updates while we triage and remediate. - We disclose the fix to you when it ships. - We credit researchers in our public security advisories (with consent) on the trust portal. ### Safe harbor Good-faith vulnerability research conducted within these guidelines is authorized — we will not pursue civil or criminal action under the Information Technology Act §43A or §66, the Indian Penal Code, or the Computer Fraud and Abuse Act for testing that: - Stays within the scope of accounts you control. - Avoids accessing or modifying other customers' data. - Avoids degrading service for other customers (no DDoS, no resource exhaustion). - Avoids social engineering of our staff. - Reports findings privately to security@splashifypro.in before public disclosure. ### Out of scope - Findings against our marketing site (splashifypro.com) — please report to the marketing-site security team via the contact form. - Theoretical vulnerabilities without proof of exploitability. - Self-XSS, missing security headers without an exploitation path, rate-limit absence on non-sensitive endpoints. - Findings against third-party services we integrate with — report to that service's security team. ## Reporting abuse If you've received spam, phishing, or fraudulent email from a sender using Splashify Pro: 1. Forward the email **with full headers preserved** to **abuse@splashifypro.in**. Include any URLs you observed and any harm that resulted (financial loss, identity theft, etc.). 2. We acknowledge within 24 hours on business days, 72 hours on weekends. 3. We investigate, take action under the [Auto-Action System](/legal/auto-actions), and respond with the outcome where confidentiality permits. For urgent matters (active phishing campaign, financial fraud in progress), include "URGENT" in the subject line. We have on-call escalation outside business hours for these. We **act on every abuse report**. Sender accounts that produce multiple credible reports are paused pending review even before our own automated detection triggers. ## Suspected breach of recipient data If you suspect a breach affecting **recipient** data (e.g. unauthorized access to your account that exposed your sending list): 1. **Lock your account immediately** — change your password, rotate all API keys, terminate active sessions from the panel. 2. Email **security@splashifypro.in** with subject "BREACH" and describe what happened and when. 3. We respond within 24 hours with: - Confirmation we received the report. - A tracking ID. - Our preliminary assessment of any cross-tenant exposure. 4. If the incident triggers our Processor obligation under the [DPA §10](/legal/data-processing-agreement#10-breach-notification), we provide formal notification within 72 hours including all information you need to fulfill your own notification obligations under DPDP Act §8(6) or GDPR Articles 33-34. If the breach is on **your** side and recipient data was exposed via your own systems (not via Splashify Pro), we still cooperate fully with your investigation and provide any supporting data we hold. ## Suspected unauthorized access to your account If you see activity in your Splashify Pro account that you don't recognize: 1. **Immediately**: - Sign out everywhere from Splashify Pro Email (Settings → Sessions → Revoke all). - Rotate every API key (Settings → API Keys → Rotate). - Change your password. - Enable two-factor authentication if not already on. 2. Email **security@splashifypro.in**: - Account ID. - The activity you didn't recognize (timestamps, sends, config changes). - What credentials you suspect were exposed. 3. We provide an account audit log going back 90 days within 24 hours, free of charge. 4. We freeze billing impact during the investigation (sends made during the unauthorized window are not retroactively credited automatically — but we credit them on case review). ## Privacy / data-protection issues For: - Data-Subject Rights requests (access, correction, erasure, portability). - Concerns about how we handle your account data. - Sub-processor objections. Email **dpo@splashifypro.in**. We respond within 30 days (DPDP Act) or one month (GDPR), extendable for complex requests. For grievance redressal under the IT (Intermediary Guidelines) Rules, 2021, escalate to **grievance@splashifypro.in**. The Grievance Officer acknowledges within 24 hours and resolves within 15 days. ## What we publish about incidents After remediation, we publish: - **Status-page incidents** — real-time during the incident, post-mortem within 14 days, at status.splashifypro.com. - **Security advisories** — on the trust portal (forthcoming) for vulnerabilities of medium severity or higher, including affected versions, mitigations, and credit to researchers (with consent). - **Annual transparency report** — summary of law-enforcement requests we received and our response. We do **not** publish: - Customer-specific incidents — these are communicated only to the affected customer. - Full technical details of fixed vulnerabilities while exploitation in the wild is plausible. ## Government and law-enforcement requests We require **valid legal process** for any disclosure of customer data — search warrant, court order, or specific statutory authority under the IT Act, CrPC, or equivalent in the requesting jurisdiction. We: - Verify the authenticity of the request. - Narrow the scope wherever the request is overbroad. - Provide notice to the affected customer **before** disclosure unless prohibited by law (e.g. a non-disclosure order). - Reject voluntary requests not backed by lawful authority. Annual statistics are published in our transparency report. ## Drills and tabletop exercises We run quarterly tabletop exercises covering: - Confirmed external compromise of the Service. - Sub-processor breach notification. - Coordinated phishing campaign by a banned sender. - Loss of access to a single sending region. Findings feed back into runbooks and engineering priorities. ## Contact escalation chain If you don't get a response in the windows above, escalate: 1. The original mailbox (security / abuse / dpo / grievance). 2. **Grievance Officer:** grievance@splashifypro.in 3. **Postal address:** Grievance Officer, EvolvePro Tech Solutions Private Limited, Shimultala, Motiganj, Bongaon, North 24 Parganas, West Bengal — 743235, India. 4. For matters governed by the IT Rules, 2021 — **Grievance Appellate Committee** under Rule 3A. 5. For matters governed by the DPDP Act — **Data Protection Board of India**. 6. For matters governed by the GDPR — your **supervisory authority** (CNIL, ICO, Garante, etc.).