SparkPost Bridge
Drop-in replacement for the SparkPost Transmissions API — keep the raw Authorization header and your existing request structure, swap in your wemail API key.
The SparkPost bridge lets you migrate from SparkPost (now Bird) to wemail without changing your integration code. Point your base URL to https://api.wemail.io/bridge/sparkpost, put your wemail API key in the same raw Authorization header, and keep the same request bodies and response shapes — transmissions, message events, and the suppression list all work the same way.
Authentication
Exactly like SparkPost, the bridge reads the API key from a plain Authorization header (no Bearer prefix). Use your wemail API key (afn_live_… or afn_test_…) where your SparkPost key used to be. Test-environment keys route through the sandbox: messages are accepted, simulated, and never delivered.
Authorization: afn_live_YOUR_WEMAIL_KEYSupported Endpoints
POST /bridge/sparkpost/api/v1/transmissions
Send a transmission — mirrors SparkPost's Create a transmission endpoint.
GET /bridge/sparkpost/api/v1/events/message
Query message events — mirrors SparkPost's Events API.
GET /bridge/sparkpost/api/v1/suppression-list
List suppressions — mirrors SparkPost's suppression list.
Field-Level Compatibility
POST /api/v1/transmissions — Request Fields
| Parameter | Type | Required | Description |
|---|---|---|---|
recipients | array | Required | [{ address: { email, name? } }] — the recipient list. |
content.from | string | object | Required | Sender ("a@b.com" or { email, name }) — must use a domain verified in your wemail workspace. |
content.subject | string | Optional | Required unless content.template_id is provided. |
content.html / content.text | string | Optional | Body parts. At least one of html, text, template_id is required. |
content.template_id | string | Optional | A wemail template id (tpl_…). SparkPost template slugs are not resolvable — re-point to the migrated template's wemail id. |
content.headers | object | Optional | Custom SMTP headers. |
substitution_data | object | Optional | Template variables, substituted like SparkPost substitution data. |
metadata | object | Optional | Custom metadata, echoed on events and webhooks. |
tags | array | Optional | Up to 10 tags. |
options | object | Optional | { open_tracking?, click_tracking?, send_at? } mapped to wemail tracking/scheduling; transactional and ip_pool are accepted and ignored. |
Response
A successful transmission returns 200 with { results: { total_rejected_recipients, total_accepted_recipients, id } }. Validation failures return 400 with { errors: [{ code, message, description }] } using SparkPost's error convention (code 1300 for invalid payloads).
GET /api/v1/suppression-list
Returns { results: [{ recipient, type, source, description, created, updated }], total_count, links }. wemail suppression types map to SparkPost sources (Bounce Rule, Spam Complaint, Manually Added). Filter with types=, from=, to=; paginate with limit.
Webhooks
When the SparkPost bridge is active, webhook deliveries are formatted exactly like SparkPost event batches: a JSON ARRAY of { msys: { message_event | track_event: { … } } } envelopes with SparkPost event vocabulary (injection, delivery, bounce, spam_complaint, open, click, list_unsubscribe, policy_rejection, delay). The shared secret travels in the X-MessageSystems-Webhook-Token header, matching SparkPost's webhook auth-token option.
Known Deviations from SparkPost API
| Parameter | Type | Required | Description |
|---|---|---|---|
template_id | behavior | Optional | SparkPost template slugs are not resolvable; use the wemail tpl_… id of the migrated template. |
ip_pool / transactional | behavior | Optional | Accepted and ignored — wemail routes bridge traffic through its own pools. |
stored recipients lists | unsupported | Optional | recipients.list_id is not supported — inline the recipient list. |
attachments / inline_images | unsupported | Optional | Not yet supported through the bridge; use the native wemail /v3/send for attachments. |
Code examples
curl -X POST https://api.wemail.io/bridge/sparkpost/api/v1/transmissions \
-H "Authorization: afn_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [{ "address": { "email": "user@example.com" } }],
"content": {
"from": "sender@yourdomain.com",
"subject": "Hello from the SparkPost bridge",
"html": "<p>It works — zero code changes.</p>"
}
}'// SparkPost SDK — point the client at the wemail bridge
const SparkPost = require('sparkpost');
const client = new SparkPost('afn_live_YOUR_KEY', {
origin: 'https://api.wemail.io/bridge/sparkpost',
});
await client.transmissions.send({
recipients: [{ address: { email: 'user@example.com' } }],
content: {
from: 'sender@yourdomain.com',
subject: 'Hello from the SparkPost bridge',
html: '<p>It works — zero code changes.</p>',
},
});import requests
resp = requests.post(
"https://api.wemail.io/bridge/sparkpost/api/v1/transmissions",
headers={"Authorization": "afn_live_YOUR_KEY"},
json={
"recipients": [{"address": {"email": "user@example.com"}}],
"content": {
"from": "sender@yourdomain.com",
"subject": "Hello from the SparkPost bridge",
"html": "<p>It works — zero code changes.</p>",
},
},
)
print(resp.status_code, resp.json()) # 200 {'results': {'id': 'msg_…', ...}}