Integrate a shipping platform
Learn how to integrate a shipping platform with Klaviyo.
Overview
This resource will help you as you build an integration between a shipping platform and Klaviyo. It walks through why shipping data belongs in Klaviyo, the recommended integration flow, the order and shipment events to send, and the authentication and certification requirements, with an API quick reference at the end.
Why connect your shipping platform to Klaviyo
Post-purchase is the highest-engagement window a brand has with a customer. Tracking emails see open rates 4 to 8 times higher than marketing emails. Owning that window inside the merchant's marketing platform, rather than a generic carrier tracking page, is where the value is. When shipping data lives in Klaviyo natively, you get measurable wins:
- Branded post-purchase comms. Replace generic carrier emails with on-brand messages going out of the merchant's existing Klaviyo account. Same look, same sender reputation, same tracking and reporting as the rest of their program.
- Drive repeat purchase from delivery confirmations. "Delivered" is the highest-intent moment in the customer lifecycle. Use it to trigger review requests, cross-sells, and replenishment flows from inside Klaviyo.
- Save WISMO support tickets. Proactive "in transit," "out for delivery," and "delayed" notifications cut a measurable share of support volume across every shipping integration we've looked at.
- Stickier merchants. Post-purchase comms tied to shipping data is one of the strongest retention signals across the partner program.
Short version: order and shipment events from your platform into the Klaviyo profile means the merchant's marketing team can own the entire post-purchase journey from the same place they run every other channel.
The flow
One-way push, partner to Klaviyo. Shipping is event-driven. The value is in the moment of status change, not persistent state, so events are the heart of this integration:
- Event emission for every status change. Order received, order shipped, in transit, out for delivery, delivered, delayed. These are the metrics the merchant builds segments and templates against.
Events fire in real time as the underlying activity happens in your platform. Each profile is keyed by email. Don't try to enrich name, phone, or address from the shipping platform. The merchant's commerce integration (Shopify, BigCommerce, etc.) already owns profile identity. Stick to writing events and the optional shipping-specific properties.
On initial install, no historical backfill is needed for most use cases. Shipping is forward-looking. If you do choose to backfill recent orders or shipments, scope it to a tight window (think 30 to 90 days) and use the bulk events job.
Events to send
Event names are not prefixed with your platform name. Branded events handle source attribution automatically when events flow through your OAuth token, so the metric name should just describe the action.
Use Title Case payload field names ("Tracking Number", "Estimated Delivery Date") so they read cleanly in the Klaviyo property picker and template editor.
Shipping events split into three streams. Most partners ship the first two. Returns is optional and only relevant if your product covers returns.
Order lifecycle events
Fire during the merchant-side fulfillment phase, before handoff to the carrier.
| Event | When it fires | Payload |
|---|---|---|
| Order Received | New order lands in the shipping platform. | Order Number, Item Names, Item Count, Order Total, Order Date, Store, Address Validation, Ship To |
| Order Awaiting Payment | Payment not yet captured. | Order Number, Order Total |
| Order Awaiting Shipment | Order is ready to ship and sitting in the merchant's fulfillment queue. | Order Number, Item Names, Item Count, Requested Shipping Service, Ship By Date, Store, Tags |
| Order On Hold | Order placed on manual hold by the merchant. | Order Number, Hold Reason |
| Order Cancelled | Order cancelled before shipment. | Order Number, Cancellation Reason, Order Total |
| Order Shipped | Label created and order handed off to the carrier. | Order Number, Tracking Number, Carrier, Service Code, Tracking URL, Estimated Delivery Date, Item Names, Item Count, Ship To |
Set $value to Order Total on Order Received, Order Shipped, and Order Cancelled. This lets the merchant see revenue attribution per metric in Klaviyo reporting.
Carrier tracking events
Fire post-handoff, driven by the carrier's tracking updates. This is where the post-purchase value sits and where most merchant flows live.
| Event | When it fires | Payload |
|---|---|---|
| Shipment In Transit | First in-transit scan after handoff. | Order Number, Tracking Number, Carrier, Tracking URL, Estimated Delivery Date |
| Shipment Out For Delivery | Carrier marks the package out for delivery. | Order Number, Tracking Number, Carrier, Tracking URL, Estimated Delivery Date |
| Shipment Delivered | Carrier confirms delivery. | Order Number, Tracking Number, Carrier, Delivered At, Item Names, Item Count |
| Shipment Delayed | Estimated delivery date slips or a carrier exception fires. | Order Number, Tracking Number, Carrier, Tracking URL, Previous Estimated Delivery Date, New Estimated Delivery Date, Exception Reason |
| Shipment Delivery Failed | Carrier failed a delivery attempt. | Order Number, Tracking Number, Carrier, Failure Reason, Next Attempt Date |
| Shipment Available For Pickup | Package held at a carrier facility or locker. | Order Number, Tracking Number, Carrier, Pickup Location, Pickup By |
| Shipment Returned To Sender | Carrier is returning the package to the merchant. | Order Number, Tracking Number, Carrier, Return Reason |
Critical implementation note: include Tracking URL on every shipment event. This is what powers "track your order" buttons in merchant templates. Without it, the merchant has to construct the deep link manually, which is error-prone and usually skipped.
Don't set $value on tracking events. These are status updates, not revenue events. Order Total already lives on the Order Shipped event upstream.
Returns events (optional)
Only emit if your product covers returns. Pure shipping partners (label printing, carrier tracking) should skip this stream. Returns partners should include it.
| Event | When it fires | Payload |
|---|---|---|
| Return Initiated | Customer files a return request. | Return ID, Order Number, Items, Return Reason, RMA Number |
| Return In Transit | Return shipment scanned by the carrier. | Return ID, Order Number, Tracking Number, Carrier |
| Return Delivered | Return received by the merchant. | Return ID, Order Number, Delivered At |
| Refund Processed | Refund issued to the customer. | Return ID, Order Number, Refund Amount |
Implementation notes (applies to all three streams):
- Create Event (
POST /api/events/) auto-creates the profile if it doesn't exist yet. Email-only identity is fine and is what every reference shipping integration uses. - Each event can update profile properties inline via the profile object on the event payload. Use this to keep the optional Last Shipment Status, Last Tracking Number, and Last Delivered At properties consistent with the latest event in a single call.
- For high-volume merchants doing very large historical backfills, use Bulk Create Events (
POST /api/event-bulk-create-jobs/). For the real-time hot path,POST /api/events/is the right default. - Use stable, well-named metric names from Day 1. Renaming a metric later means rebuilding every segment and template that references it.
Auth, scopes, and certification
Build as a public OAuth app. Private API keys are a non-starter for the marketplace. Start with the Create a public OAuth app guide.
Key OAuth specifics for shipping integrations:
- PKCE is required on the authorization code exchange (
code_verifiermust be included). - Access tokens are short-lived (1 hour). Refresh tokens are long-lived but rotate on every use. Persist the latest refresh token after every refresh call, or you'll lose the integration on the next refresh.
- Tokens are scoped per Klaviyo account. Merchants with multiple Klaviyo accounts (brands, regions, prod and test) install separately for each.
Scopes to request:
profiles:writefor writing the optional Last Shipment properties to profiles.events:writefor emitting order and shipment events.profiles:readonly if your integration also reads existing profile state. Most shipping integrations don't need this. Don't over-scope. It gets flagged in marketplace review.
Branded metric badges happen automatically when events flow through the OAuth token. No extra payload field is needed. The integration source is identified by the token itself.
Once functional, submit for App Marketplace review. Plan for at least one round of feedback. The review covers OAuth, scopes, install and uninstall validation, and that the integration delivers what your listing claims.
API quick reference
Concrete specs for AI coding assistants and engineers grounding on this doc. The narrative above is the why and the flow. This section is the what-to-actually-type.
Headers (required on every request)
Authorization: Bearer <oauth_access_token>
revision: 2026-04-15
Accept: application/json
Content-Type: application/json
Pin the revision header to a specific date when you ship. Check the API versioning guide for the current latest. Without it you'll get a 400.
Event POST body
Send a shipment event. The event creates the profile if it doesn't exist, and updates the optional shipping properties on the profile inline.
POST /api/events/
{
"data": {
"type": "event",
"attributes": {
"properties": {
"Order Number": "1042",
"Tracking Number": "1Z999AA10123456784",
"Carrier": "UPS",
"Tracking URL": "https://yourbrand.com/track/1Z999AA10123456784",
"Estimated Delivery Date": "2026-06-05",
"Item Names": ["Linen Shirt", "Canvas Tote"],
"Item Count": 2
},
"metric": {
"data": {
"type": "metric",
"attributes": { "name": "Shipment Out For Delivery" }
}
},
"profile": {
"data": {
"type": "profile",
"attributes": {
"email": "[email protected]",
"properties": {
"{Platform} Last Tracking Number": "1Z999AA10123456784",
"{Platform} Last Shipment Status": "out_for_delivery"
}
}
}
}
}
}
}
Order event with revenue
On order lifecycle events, include $value so the merchant sees revenue attribution per metric in reporting.
POST /api/events/
{
"data": {
"type": "event",
"attributes": {
"properties": {
"Order Number": "1042",
"Item Names": ["Linen Shirt", "Canvas Tote"],
"Item Count": 2,
"Order Total": 89.50,
"Order Date": "2026-05-29T14:22:11Z",
"$value": 89.50
},
"metric": {
"data": {
"type": "metric",
"attributes": { "name": "Order Shipped" }
}
},
"profile": {
"data": {
"type": "profile",
"attributes": { "email": "[email protected]" }
}
}
}
}
}
Retries
- 429: respect the
Retry-Afterheader. Otherwise exponential backoff starting at 1s, cap at 60s, max 5 retries. - 5xx: same backoff.
- 4xx (other than 429): don't retry. Log and surface to the merchant.
Identifier guidance
- Identify by email first; phone where you have it. These are the fields Klaviyo merges on.
- Don't enrich profile name, phone, or address from the shipping platform. The merchant's commerce integration (Shopify, BigCommerce, etc.) already owns profile identity. Sending stale or partial identity data risks overwriting good data on the profile.
- If the order doesn't have a customer email, drop the event. Don't try to invent identity from the shipping address.
Rate limits
Per-account, not per-app. Standard limits handle typical shipping volume without effort. For merchants at unusual scale (think 10M+ shipment events per day), the path is per-endpoint, per-account increases through Klaviyo Support and CSM. Reach out before launch so we can fast-track the request rather than ramping into 429s in production.
Glossary
- Klaviyo profile: customer record. Keyed by email, phone, or external ID.
- Klaviyo metric: event type. "Order Shipped," "Shipment Delivered," etc. Created automatically on first event ingest.
- Klaviyo segment: dynamic audience computed from rules. The merchant builds these from your profile properties and events to target post-purchase audiences.
- Tracking event: a status update from the carrier (in transit, out for delivery, delivered, etc.). Distinct from order lifecycle events, which fire during merchant-side fulfillment before carrier handoff.
- Carrier exception: any non-happy-path tracking status from the carrier. Delays, failed delivery attempts, returned to sender.
- RMA (Return Merchandise Authorization): the identifier for a customer-initiated return. Relevant only if your product covers returns.
Resources
- Klaviyo Developer Portal. Start here for everything.
- Create a public OAuth app
- Create Event / Bulk Create Events / Update Profile
- Klaviyo App Marketplace, Shipping category. The existing set of shipping integrations.
- App Marketplace Review: [email protected]
Updated about 16 hours ago