How to create an abandoned checkout automation
Intro
Build an automation that re-engages shoppers who began checkout but did not complete a purchase. The workflow waits for inactivity, sends a reminder email, follows up with an SMS, and tags the contact for further segmentation.
See API reference: Automations | Event Metadata
Prerequisites
- An API key with
automations.writescope (addemail-templates.writeif creating a new template), or an OAuth token with the same scopes - Your store must already be sending the
started checkoutevent — see How to enable cart/checkout abandonment for setup instructions - An email template prepared for the checkout reminder (see Email Templates API)
Block types used in this guide
This automation uses four block types:
| Block type | Purpose | Key fields |
|---|---|---|
| delay | Pauses the workflow before the next block executes. Mode can be duration (wait N time units), immediate (no wait), or specificTime (wait until a clock time). | mode, duration.amount, duration.units |
| action → sendEmail | Sends an email using a pre-built template. The template content is copied into the automation at creation time. | templateID (required), subject, senderName, preheader, language |
| action → sendSms | Sends an SMS (or MMS in US/CA with an image). Requires a message body and compliance settings for opt-out text. | message, compliance |
| action → addTag | Adds a tag to the contact for segmentation or downstream logic. Tags are case-insensitive. | value (the tag string) |
Step 1: Look up the trigger event metadata
Before building the automation, verify that the started checkout event is available for your brand and identify the correct origin value. The Event Metadata API returns event names, origins, and property paths your brand can use.
See endpoint: Query events metadata
curl -X POST 'https://api.omnisend.com/api/event-metadata' \
-H 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
-H 'Omnisend-Version: 2026-preview' \
-H 'Content-Type: application/json' \
-d '{
"category": "automations",
"events": ["started checkout"],
"includeProperties": true
}'The response lists each origin that provides this event for your brand (e.g. shopify, api, woocommerce) and the property paths you can use in trigger filters. Use the origins array from the response to set the correct origin in Step 2.
Note: If the response is empty, your store is not sending
started checkoutevents yet. Follow the cart/checkout abandonment setup guide first.
Step 2: Create the automation
Create the abandoned checkout automation with a trigger, exit condition, inactivity timer, and the full block sequence: email → delay → SMS → tag.
The inactivitySettings ensures the workflow only fires after the shopper has been idle for 1 hour — any new checkout activity resets the timer, so the email reflects their final cart.
See endpoint: Create automation workflow
curl -X POST 'https://api.omnisend.com/api/automations' \
-H 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
-H 'Omnisend-Version: 2026-preview' \
-H 'Content-Type: application/json' \
-d '{
"name": "Abandoned Checkout Recovery",
"trigger": {
"condition": {
"event": "started checkout",
"origin": "api"
},
"inactivitySettings": {
"duration": { "amount": 1, "units": "h" }
}
},
"exitConditions": [
{
"event": "placed order",
"origin": "api"
}
],
"blocks": [
{
"temporaryID": "email-reminder",
"type": "action",
"action": {
"type": "sendEmail",
"sendEmail": {
"templateID": "000000000000000000000001",
"subject": "You left something behind!",
"senderName": "My Store",
"preheader": "Complete your order before items sell out",
"language": "en_US"
}
}
},
{
"temporaryID": "wait-24h",
"type": "delay",
"delay": {
"mode": "duration",
"duration": { "amount": 24, "units": "h" }
}
},
{
"temporaryID": "sms-followup",
"type": "action",
"action": {
"type": "sendSms",
"sendSms": {
"message": "Hi [[contact.first_name]], your cart is still waiting! Complete your checkout: [[checkout_url]]",
"compliance": {
"isStopKeywordIncluded": true,
"stopKeywordText": "Reply STOP to opt out",
"isUnsubscribeLinkIncluded": true,
"unsubscribeLinkText": "Unsubscribe [[unsubscribe_link]]"
}
}
}
},
{
"temporaryID": "tag-reached-sms",
"type": "action",
"action": {
"type": "addTag",
"addTag": {
"value": "reached_abandonment_sms"
}
}
}
]
}'The response returns the automation in disabled state with a server-assigned id. Save this ID for the enable step.
Note: Replace
"origin": "api"with the origin returned by the Event Metadata endpoint in Step 1 (e.g."shopify","woocommerce"). The origin must match both the trigger and the exit condition.
Note:
exitConditionsuses OR logic — the contact exits immediately when any listed event fires. Here, a singleplaced orderevent removes the contact so they do not receive further reminders after purchasing.
Step 3: Enable the automation
Activate the automation so it starts processing trigger events.
See endpoint: Enable automation workflow
curl -X POST 'https://api.omnisend.com/api/automations/AUTOMATION_ID/enable' \
-H 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
-H 'Omnisend-Version: 2026-preview' \
-H 'Content-Type: application/json' \
-d '{
"enrollExisting": false
}'A 200 response confirms the automation is now enabled. The isEnabled field is true and enabledAt shows the activation timestamp.
Note: The
enrollExistingoption retroactively enrolls contacts whose trigger event occurred within the first delay block's time window. It requires a delay block as the very first step in the workflow. The automation above starts with an action (email), soenrollExisting: trueis rejected with409. To use it, insert a delay block before the email — its duration defines how far back the engine looks for qualifying events.
Verify results
Retrieve the automation to confirm it is enabled and all blocks are in place.
See endpoint: Get automation workflow
curl -X GET 'https://api.omnisend.com/api/automations/AUTOMATION_ID' \
-H 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
-H 'Omnisend-Version: 2026-preview'Check that isEnabled is true and blocks contains the four blocks you defined. Each block now has a server-assigned id replacing the temporaryID you provided.
Troubleshooting
- 409 Conflict on enable with
enrollExisting: The automation must start with a delay block as its first step. Add a delay block before the first action — its duration defines the enrollment window for past events. - 400 on create — origin mismatch: The
originintrigger.conditionandexitConditionsmust be an origin your brand has event data for. Use the Event Metadata endpoint to check available origins. - 409 Conflict on PATCH while enabled: The automation is currently enabled. Disable it first via
POST /automations/{id}/disable, make changes, then re-enable. - SMS not delivered: Contacts must be SMS-subscribed. The default
sendingThresholdsissubscribed— non-subscribers are skipped (controlled byisSkipAllowedon the block).