Access is invite-only during beta. Once invited, create a key to personalize these examples. Production sending requires a separate review.

Switching from SendGrid

Keep the Event Webhook array and optional Inbound Parse fields. Replace send credentials and webhook verification.

PostShiba keeps parts of three useful SendGrid contracts. Delivery webhooks remain JSON arrays with compatible delivery fields. SMTP reads unique_args inside X-SMTPAPI. Inboxes can post familiar Inbound Parse fields. The /v3/mail/send endpoint, SG. keys, subuser credentials, ECDSA or OAuth webhook checks, and open or click events do not carry over.

Run SendGrid and PostShiba together

Run both providers during outbound migration. Route a deterministic cohort by tenant or customer ID, or feature-flag one message class. Each real message must use exactly one provider. Never dual-send it.

Start with this adjustable 30-day ramp. Change the stage lengths for your volume, and advance only while checks remain healthy:

  1. Days 1 through 3. Run controlled tests with representative payloads.
  2. Days 4 through 9. Route 10% of new outbound traffic to PostShiba.
  3. Days 10 through 15. Increase the share to 25%.
  4. Days 16 through 22. Increase the share to 50%.
  5. Days 23 through 30. Route 100% of new outbound traffic to PostShiba.

PostShiba uses shared IPs. This ramp validates payloads, webhooks, suppressions, and traffic from each sender and domain. It is not dedicated-IP warming.

Keep SendGrid keys, webhooks, routes, and DNS through rollback. Authentication records can coexist unless DKIM selectors or return-path hosts collide. On collision, use a separate PostShiba sending subdomain.

Handle inbound MX as a separate cutover. Percentage routing and equal-priority MX records do not provide a controlled split. Test a hosted inbox or new inbound subdomain before switching MX.

Inventory your SendGrid use

Before you change production, record:

  • /v3/mail/send callers and SMTP clients, with their keys and sending domains.
  • Subusers and their domains, credentials, suppressions, and inbound routes.
  • custom_args and X-SMTPAPI.unique_args fields used by event handlers.
  • Event Webhook URLs, event types, ECDSA keys, and OAuth checks.
  • Inbound Parse hostnames, MX records, destination URLs, and attachment assumptions.
  • Dynamic Templates, send_at, ASM groups, and ip_pool_name that need replacement or removal.

Map the concepts

SendGrid PostShiba
Account and SG. API key Team and team-locked API key
/v3/mail/send Flat JSON on POST /api/v1/emails
smtp.sendgrid.net, username apikey smtp.postshiba.com, issued smtp_... username
Subuser Tenant
Authenticated domain Verified sending domain with DKIM and return-path records
IP pool Shared cluster. There is no customer-selected IP pool.
V3 custom_args Top-level unique_args
Event Webhook SendGrid-shaped JSON array with X-Capsule-* HMAC headers
Inbound Parse Inbox with optional sendgrid_parse format

Prepare PostShiba

  1. Create one shared cluster and wait for sending_ready. Request production approval. Pending teams can send only to members and live inboxes.
  2. Create an API key. Keep it server-side and use Authorization: Bearer.
  3. Map isolated subusers to tenants. Tenants scope resources and suppressions, not SendGrid logins, API keys, quotas, statistics, or IP assignments. Otherwise, use the default tenant.
  4. Add and verify each sending domain under its tenant. Publish its DKIM and return-path CNAME records.
  5. Issue a cluster credential for each extra tenant and each SMTP client.

Bring your suppressions

Import SendGrid bounces, blocks, spam reports, unsubscribes, and group suppressions before you send. A missed row is a complaint on the new cluster.

Export each list as CSV from the SendGrid Suppressions pages, or pull them from the Suppression API. Map isolated subuser lists to the matching tenant.

Upload the CSV on Suppressions, or post the addresses:

import-suppressions.sh
1 curl -sS -X POST \
2 -H 'Authorization: Bearer YOUR_POSTSHIBA_TOKEN' \
3 -H 'Content-Type: application/json' \
4 -d '{
5 "emails": ["unsubscribed@example.com", "bounced@example.com"],
6 "tenant_id": "WbLcFd"
7 }' \
8 https://app.postshiba.com/api/v1/teams/KjkAJW/suppressions/import

Use a column named email, address, or recipient, or one address per line. Existing rows are skipped. Max 10,000 addresses per request. See Suppressions.

Migrate one HTTP send

For one personalization, combine from.email and from.name in from. Convert recipients to address strings. Move content into text and html, and V3 custom_args into unique_args. Send separate requests for different content or metadata.

migrate-receipt.sh
1 curl -sS -X POST \
2 -H 'Authorization: Bearer YOUR_POSTSHIBA_TOKEN' \
3 -H 'Content-Type: application/json' \
4 -d '{
5 "from": "Acme Receipts <receipts@mail.example.com>",
6 "to": ["alex@example.com"],
7 "subject": "Receipt ord_123",
8 "text": "Thanks for your order.",
9 "html": "<p>Thanks for your order.</p>",
10 "unique_args": {
11 "order_id": "ord_123",
12 "source": "checkout"
13 },
14 "tenant": "acme"
15 }' \
16 https://app.postshiba.com/api/v1/emails

Expect HTTP 201 with queued: true and a message_id. Render Dynamic Templates first. Move send_at to your job queue and ASM rules to your consent system. Remove ip_pool_name; clusters use shared IPs.

Use only a confirmed tenant ID or slug. An unknown tenant value is 422 {error: invalid, field: tenant}.

POST /api/v1/emails has no idempotency key. For ambiguous-response retries, use cluster-specific POST /sends with Idempotency-Key. Otherwise, reconcile before sending again.

PostShiba accepts at most 32 scalar unique_args. Keys are limited to 64 bytes and values to 256 bytes. See the unique args rules for reserved fields.

For SMTP, use STARTTLS on port 587 with AUTH PLAIN. Replace username apikey and the SG. password with an issued smtp_... username and password. Keep X-SMTPAPI only for its nested unique_args object, or use X-Capsule-Unique-Args. PostShiba ignores other X-SMTPAPI instructions and strips the header before delivery.

Before the first production cohort, export hard bounces, invalid addresses, spam reports, and global unsubscribes into the matching tenant suppressions. Do not import temporary Blocks as permanent suppressions. Keep ASM group preferences in your application. While both providers run, write new complaints and unsubscribes to the consent source used by both send paths.

Move delivery webhooks

Add a delivery webhook and keep the outer-array parser. SendGrid can batch events, while each PostShiba request contains one event inside the array. Audit fields rather than assuming full parity. PostShiba emits processed, delivered, deferred, bounce, dropped, spamreport, and unsubscribe. It does not emit open or click.

Replace SendGrid ECDSA and OAuth verification on this route. Verify the PostShiba request with the endpoint secret, raw body, X-Capsule-Timestamp, and X-Capsule-Signature. The signature is sha256= plus hex HMAC-SHA256 over {timestamp}.{raw_body}.

Send the receipt example and confirm that order_id, source, and sg_message_id reach the handler. Remove launch checks that wait for open or click.

Move Inbound Parse

Create a domain-bound inbox and select sendgrid_parse. It includes familiar fields such as to, from, subject, text, html, raw MIME in email, attachment1, and attachment-info. PostShiba sends URL-encoded form data, not SendGrid multipart uploads. Test attachment handling.

Publish MX on inbound.{sending_domain} to inbound.postshiba.com. Leave the sending domain's MX records alone. Inbound posts use the same X-Capsule-* HMAC headers.

Validate, cut over, and roll back

  1. While KYC is pending, send tests to a team member or live inbox. Check content, DKIM, return path, metadata, and delivery events.
  2. After approval, follow the outbound ramp. At each stage, check delivery, bounce, deferral, complaint, unsubscribe, and suppression handling.
  3. Test Inbound Parse fields, attachments, and webhooks before switching inbound MX.
  4. At 100%, wait through the observation and DNS rollback windows. Then revoke SendGrid keys and remove its webhooks, inbound route, and obsolete DNS records.

For outbound rollback, route only new, unsent messages to SendGrid. A PostShiba 201 means accepted, so keep its webhook online for late events instead of replaying the message. For inbound rollback, restore the old MX target and allow for DNS TTL.

Cutover checklist

  • The shared cluster reports sending_ready, and KYC is approved.
  • Sending domains, tenants, and tenant credentials match the SendGrid inventory.
  • A real HTTP or SMTP send returns a delivery event with unique_args.
  • Webhook HMAC verification uses the raw body and PostShiba headers.
  • No monitor or workflow requires open or click.
  • Suppressions and ASM preferences are enforced before the first production cohort.
  • Inbound Parse fields, attachments, MX, and rollback were tested.
  • Bounce, block, spam report, and unsubscribe lists are imported per tenant.
  • The router assigns each real message to exactly one provider.

About

PostShiba is the email platform that powers Bento behind the scenes. You can build your own products, like Bento, on top of it.

© 2026 PostShiba by Backpack Internet Pty. Ltd. All rights reserved.

The same policies that govern Bento are applied to PostShiba Privacy | Terms | Security