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.

bashAuthentication header
Authorization: afn_live_YOUR_WEMAIL_KEY

Supported 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

Transmission request fields
ParameterTypeRequiredDescription
recipientsarrayRequired[{ address: { email, name? } }] — the recipient list.
content.fromstring | objectRequiredSender ("a@b.com" or { email, name }) — must use a domain verified in your wemail workspace.
content.subjectstringOptionalRequired unless content.template_id is provided.
content.html / content.textstringOptionalBody parts. At least one of html, text, template_id is required.
content.template_idstringOptionalA wemail template id (tpl_…). SparkPost template slugs are not resolvable — re-point to the migrated template's wemail id.
content.headersobjectOptionalCustom SMTP headers.
substitution_dataobjectOptionalTemplate variables, substituted like SparkPost substitution data.
metadataobjectOptionalCustom metadata, echoed on events and webhooks.
tagsarrayOptionalUp to 10 tags.
optionsobjectOptional{ 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

Deviations
ParameterTypeRequiredDescription
template_idbehaviorOptionalSparkPost template slugs are not resolvable; use the wemail tpl_… id of the migrated template.
ip_pool / transactionalbehaviorOptionalAccepted and ignored — wemail routes bridge traffic through its own pools.
stored recipients listsunsupportedOptionalrecipients.list_id is not supported — inline the recipient list.
attachments / inline_imagesunsupportedOptionalNot yet supported through the bridge; use the native wemail /v3/send for attachments.

Code examples

cURL
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>"
    }
  }'
Node.js
// 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>',
  },
});
Python
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_…', ...}}