SendGrid Bridge

Drop-in replacement for the SendGrid v3 Mail Send API — use your wemail API key, keep your existing request structure.

The SendGrid bridge lets you migrate from SendGrid to wemail without changing your integration code. Point your base URL to https://api.wemail.io/bridge/sendgrid, swap your SendGrid API key for a wemail API key, and keep the same request bodies, headers, and response shapes. The bridge translates every call into the wemail pipeline — delivery, tracking, webhooks, and suppressions all work the same way.

API Version & Authentication

ParameterTypeRequiredDescription
API Versionv3OptionalMatches SendGrid v3 URL structure.
Auth MethodBearer TokenOptionalAuthorization: Bearer afn_live_YOUR_KEY
Base URLURLOptionalhttps://api.wemail.io/bridge/sendgrid

Supported Endpoints

ParameterTypeRequiredDescription
POST /v3/mail/sendSupportedOptionalPersonalizations, content, templates, tracking, categories, custom_args, headers, CC/BCC, reply_to, send_at, substitutions.
GET /v3/messagesSupportedOptionalList recent messages with limit param. opens_count and clicks_count always return 0.
GET /v3/suppression/bouncesSupportedOptionalList bounces with start_time, end_time, limit filtering.
GET /v3/suppression/spam_reportsSupportedOptionalList spam reports with start_time, end_time, limit filtering.

SendGrid v3 API Compatibility Matrix

ParameterTypeRequiredDescription
Mail Send (POST /v3/mail/send)SupportedOptionalPersonalizations, content, templates, tracking, categories, CC/BCC, reply_to, send_at. Attachments not yet supported.
Email Activity / Messages (GET /v3/messages)Partially SupportedOptionalList recent messages with limit. opens_count and clicks_count hardcoded to 0. No query filter support.
Suppressions — BouncesSupportedOptionalList with time range filtering. Delete/get individual bounce not supported.
Suppressions — Spam ReportsSupportedOptionalList with time range filtering. Delete/get individual not supported.
Suppressions — BlocksNot SupportedOptional
Suppressions — Invalid EmailsNot SupportedOptional
Suppressions — Unsubscribes (Global)Not SupportedOptional
Templates / Dynamic TemplatesNot SupportedOptionaltemplate_id can be passed in mail/send but template CRUD is not available.
Contacts / MarketingNot SupportedOptionalMarketing campaigns, lists, segments, contacts.
Stats (Global/Category/Subuser)Not SupportedOptional
Subuser ManagementNot SupportedOptional
IP Management (IPs, Pools, Warmup)Not SupportedOptional
Domain AuthenticationNot SupportedOptionalUse wemail console for domain management.
Link BrandingNot SupportedOptional
Webhooks (Event/Inbound Parse)Not SupportedOptionalUse wemail webhook configuration.
Sender VerificationNot SupportedOptional
API Keys ManagementNot SupportedOptionalUse wemail console for API key management.
TeammatesNot SupportedOptional
CategoriesNot SupportedOptionalCategories can be set via mail/send but CRUD is not available.
AlertsNot SupportedOptional
Scheduled Sends (Cancel/Pause)Not SupportedOptionalsend_at supported in mail/send but cancel/pause not available.
Email ValidationNot SupportedOptionalUse wemail /v3/validate endpoint instead.

Field-Level Compatibility

Detailed breakdown of every request field and response field across all supported endpoints.

POST /v3/mail/send — Request Fields

ParameterTypeRequiredDescription
personalizations[].toSupportedRequiredArray of { email, name } recipients. At least one required.
personalizations[].ccSupportedOptionalCC recipients.
personalizations[].bccSupportedOptionalBCC recipients.
personalizations[].subjectSupportedOptionalOverrides top-level subject for this personalization.
personalizations[].substitutionsSupportedOptionalKey-value string replacements applied to content.
personalizations[].custom_argsSupportedOptionalMerged with top-level custom_args as metadata.
personalizations[].send_atSupportedOptionalUnix timestamp. Overrides top-level send_at.
personalizations[].headersSupportedOptionalMerged with top-level headers.
personalizations[].dynamic_template_dataNot SupportedOptionalIgnored. Use substitutions instead.
fromSupportedRequired{ email, name }. Domain must be verified in your account.
reply_toSupportedOptional{ email, name } reply-to address.
subjectSupportedOptionalRequired unless template_id is set or every personalization has a subject.
content[].typeSupportedOptionaltext/html and text/plain supported.
content[].valueSupportedOptionalThe email body content.
template_idSupportedOptionalPassed through to wemail template engine.
categoriesSupportedOptionalMapped to wemail tags (max 10).
custom_argsSupportedOptionalStored as message metadata.
send_atSupportedOptionalUnix timestamp for scheduled delivery.
headersSupportedOptionalCustom email headers.
tracking_settings.open_tracking.enableSupportedOptionalEnable/disable open tracking.
tracking_settings.click_tracking.enableSupportedOptionalEnable/disable click tracking.
attachmentsNot SupportedOptionalSilently ignored. Message sends without attachments.
asm (unsubscribe groups)Not SupportedOptionalIgnored.
mail_settingsNot SupportedOptionalIgnored (sandbox_mode, bcc, footer, spam_check).
batch_idNot SupportedOptionalIgnored. Cancel/pause scheduled sends not available.
ip_pool_nameNot SupportedOptionalIgnored.

POST /v3/mail/send — Response

ParameterTypeRequiredDescription
Status 202SupportedOptionalEmpty body on success (matches SendGrid).
X-Message-Id headerSupportedOptionalwemail message ID in response header.
errors[]SupportedOptionalOn failure: { message, field, help } matching SendGrid error format.

GET /v3/messages — Request & Response

ParameterTypeRequiredDescription
limit (query)SupportedOptionalMax results (default 50, max 1000).
query (query)Not SupportedOptionalSendGrid query filter syntax not implemented.
Response: msg_idSupportedOptionalwemail message ID.
Response: from_emailSupportedOptionalSender address.
Response: to_emailSupportedOptionalFirst recipient.
Response: subjectSupportedOptionalMessage subject.
Response: statusSupportedOptionalMapped: queued->processing, sent->processed, delivered->delivered, bounced->not_delivered.
Response: opens_countHardcoded 0OptionalAlways returns 0. Use wemail events API.
Response: clicks_countHardcoded 0OptionalAlways returns 0. Use wemail events API.
Response: last_event_timeSupportedOptionalISO 8601 timestamp.

GET /v3/suppression/bounces — Request & Response

ParameterTypeRequiredDescription
start_time (query)SupportedOptionalUnix timestamp filter.
end_time (query)SupportedOptionalUnix timestamp filter.
limit (query)SupportedOptionalDefault 100, max 500.
offset (query)Not SupportedOptionalAccepted but ignored.
Response: emailSupportedOptionalBounced email address.
Response: reasonSupportedOptionalBounce reason.
Response: statusHardcodedOptionalAlways 5.1.1.
Response: createdSupportedOptionalUnix timestamp.

GET /v3/suppression/spam_reports — Request & Response

ParameterTypeRequiredDescription
start_time (query)SupportedOptionalUnix timestamp filter.
end_time (query)SupportedOptionalUnix timestamp filter.
limit (query)SupportedOptionalDefault 100, max 500.
Response: emailSupportedOptionalComplainant email.
Response: reasonSupportedOptionalComplaint reason.
Response: createdSupportedOptionalUnix timestamp.
Response: ipHardcodedOptionalAlways empty string.

SDK Downloads

Download the official SendGrid SDK pre-configured for the wemail bridge. The base URL is already set to https://api.wemail.io/bridge/sendgrid — just unzip and use with your wemail API key.

LanguagePackageInstallRegistry
Node.js@sendgrid/mailnpm
PythonsendgridPyPI
PHPsendgrid/sendgridPackagist
Rubysendgrid-rubyRubyGems
Gosendgrid-goGitHub
Javasendgrid-javaMaven
C#SendGridNuGet

Known Deviations from SendGrid API

Attachments — The attachments array in POST /v3/mail/send is not yet supported. Requests that include attachments will send the message without them.

Error format — Errors match the SendGrid structure: { "errors": [{ "message": "...", "field": "...", "help": "..." }] }.

Auto-creation — The bridge account is automatically created on the first authenticated request. No setup step is required.

Status mapping — The status field in messages uses the SendGrid vocabulary: queuedprocessing, sentprocessed, etc.

Migrating for good? Follow the SendGrid migration guide — templates and suppressions auto-import, and SendGrid stays warm for 30 days.

Code examples

cURL
curl -X POST https://api.wemail.io/bridge/sendgrid/v3/mail/send \
  -H "Authorization: Bearer afn_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "personalizations": [
      {
        "to": [{ "email": "user@example.com" }]
      }
    ],
    "from": { "email": "sender@yourdomain.com" },
    "subject": "Hello from wemail",
    "content": [
      {
        "type": "text/html",
        "value": "<p>Hello World</p>"
      }
    ]
  }'
Node.js
// Official SDK: npm i @sendgrid/mail
const client = require('@sendgrid/client');
const sgMail = require('@sendgrid/mail');

// Point the official SendGrid SDK at the wemail bridge
client.setApiKey('afn_live_YOUR_KEY');
client.setDefaultRequest('baseUrl', 'https://api.wemail.io/bridge/sendgrid');
sgMail.setClient(client);

await sgMail.send({
  to: 'user@example.com',
  from: 'sender@yourdomain.com',
  subject: 'Hello from wemail',
  html: '<p>Hello World</p>',
});
Python
# Official SDK: pip install sendgrid
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail

message = Mail(
    from_email='sender@yourdomain.com',
    to_emails='user@example.com',
    subject='Hello from wemail',
    html_content='<p>Hello World</p>')

# Point the official SendGrid SDK at the wemail bridge
sg = SendGridAPIClient('afn_live_YOUR_KEY', host='https://api.wemail.io/bridge/sendgrid')
response = sg.send(message)
print(response.status_code)  # 202
PHP
<?php
// Official SDK: composer require sendgrid/sendgrid
$email = new \SendGrid\Mail\Mail();
$email->setFrom('sender@yourdomain.com');
$email->addTo('user@example.com');
$email->setSubject('Hello from wemail');
$email->addContent('text/html', '<p>Hello World</p>');

// Point the official SendGrid SDK at the wemail bridge
$sendgrid = new \SendGrid('afn_live_YOUR_KEY', ['host' => 'https://api.wemail.io/bridge/sendgrid']);
$response = $sendgrid->send($email);

echo $response->statusCode(); // 202
Ruby
# Official SDK: gem install sendgrid-ruby
require 'sendgrid-ruby'
include SendGrid

from    = SendGrid::Email.new(email: 'sender@yourdomain.com')
to      = SendGrid::Email.new(email: 'user@example.com')
content = SendGrid::Content.new(type: 'text/html', value: '<p>Hello World</p>')
mail    = SendGrid::Mail.new(from, 'Hello from wemail', to, content)

# Point the official SendGrid SDK at the wemail bridge
sg = SendGrid::API.new(api_key: 'afn_live_YOUR_KEY', host: 'https://api.wemail.io/bridge/sendgrid')
response = sg.client.mail._('send').post(request_body: mail.to_json)
puts response.status_code  # 202
Go
// Official SDK: go get github.com/sendgrid/sendgrid-go
package main

import (
	"fmt"
	"github.com/sendgrid/sendgrid-go"
	"github.com/sendgrid/sendgrid-go/helpers/mail"
)

func main() {
	from := mail.NewEmail("Sender", "sender@yourdomain.com")
	to := mail.NewEmail("User", "user@example.com")
	msg := mail.NewSingleEmail(from, "Hello from wemail", to, "", "<p>Hello World</p>")

	// Point the official SendGrid SDK at the wemail bridge
	request := sendgrid.GetRequest("afn_live_YOUR_KEY", "/v3/mail/send", "https://api.wemail.io/bridge/sendgrid")
	request.Method = "POST"
	request.Body = mail.GetRequestBody(msg)

	response, err := sendgrid.API(request)
	if err != nil {
		panic(err)
	}
	fmt.Println(response.StatusCode) // 202
}
Java
// Official SDK: com.sendgrid:sendgrid-java
import com.sendgrid.*;
import com.sendgrid.helpers.mail.Mail;
import com.sendgrid.helpers.mail.objects.*;

public class SendGridBridge {
    public static void main(String[] args) throws Exception {
        Email from = new Email("sender@yourdomain.com");
        Email to = new Email("user@example.com");
        Content content = new Content("text/html", "<p>Hello World</p>");
        Mail mail = new Mail(from, "Hello from wemail", to, content);

        // Point the official SendGrid SDK at the wemail bridge
        SendGrid sg = new SendGrid("afn_live_YOUR_KEY");
        sg.setHost("api.wemail.io/bridge/sendgrid");

        Request request = new Request();
        request.setMethod(Method.POST);
        request.setEndpoint("mail/send");
        request.setBody(mail.build());

        Response response = sg.api(request);
        System.out.println(response.getStatusCode()); // 202
    }
}
C#
// Official SDK: dotnet add package SendGrid
using SendGrid;
using SendGrid.Helpers.Mail;

// Point the official SendGrid SDK at the wemail bridge
var client = new SendGridClient(new SendGridClientOptions
{
    ApiKey = "afn_live_YOUR_KEY",
    Host = "https://api.wemail.io/bridge/sendgrid"
});

var msg = MailHelper.CreateSingleEmail(
    new EmailAddress("sender@yourdomain.com"),
    new EmailAddress("user@example.com"),
    "Hello from wemail", "", "<p>Hello World</p>");

var response = await client.SendEmailAsync(msg);
Console.WriteLine((int)response.StatusCode); // 202
Response
// 202 Accepted — no response body
// (matches SendGrid behavior)