External events
The ShopiMind API lets you trigger marketing automation scenarios from any third-party system — POS, ERP, survey platform, carrier, in-house scheduler — via custom events. This is the recommended path to connect a business event to a ShopiMind customer journey without coupling the systems.
The three-step model
- Declare an event type via
createEvent. You define itscode_name(used in the trigger URL), its payload structure (metaData,customData) and the expected target (a contact or a visitor). - Configure in the ShopiMind dashboard an automation scenario whose trigger is the custom event type previously created. On save, ShopiMind automatically wires the event to the scenario — no extra API call is needed on the third-party side.
- Fire an instance via
triggerEventwith thecode_nameand a payload matching the schema defined in step 1. All active scenarios subscribed to thatcode_nameare triggered.
Emission is asynchronous: triggerEvent returns as soon as the event is queued. Scenario execution follows, in near real-time.
Steps 1 and 2 are independent
You can declare the event type via the API before the scenario exists on the dashboard, or the other way around. The connection is made by code_name: as long as it matches, the event triggers the subscribed scenarios.
Anatomy of an event type
An event type declares a schema (properties) that is validated on every trigger. Four payload slots are supported:
| Slot | Context |
|---|---|
metaData | Free metadata describing the event's context. |
customData | Free custom data attached to the event instance. |
contact.customData | Custom data attached to the resolved contact. |
visitor.customData | Custom data attached to the resolved visitor. |
Each field in the schema specifies:
| Key | Role |
|---|---|
name | Expected key in the payload. |
type | bool, text, longtext, number, decimal, date or json. |
required | Boolean — if true, missing this field rejects the triggerEvent call. |
description | Optional — descriptive label (useful for dashboard segmentation). |
code_name format
The code_name is the slug used in the trigger URL (/events/trigger/:code_name). It must follow one of these formats:
- a single alphanumeric word:
store_purchase,nps_received,delivered; - a
Resource.ActionorResource_Actionnotation:Order.Created,Subscription_Renewed.
Spaces and special characters are rejected. Changing code_name via updateEvent immediately rotates the trigger URL: switch emitters to the new value before the change to avoid downtime on the third-party side.
Target: contact or visitor
The triggerEvent payload must contain at least one of the two objects:
contact— resolved by one of the identifiersid,email, orphone. At least one of the three is required.visitor— resolved by itsid(required).
If the target isn't found, the event is still logged in history but no scenario is triggered.
Example — declare an event type
curl -X POST https://api.shopimind.com/v1/events \
-H "spm-api-key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Physical store purchase",
"code_name": "store_purchase",
"properties": {
"metaData": [
{ "name": "order_id", "type": "number", "required": true },
{ "name": "total_amount", "type": "decimal", "required": true },
{ "name": "store_code", "type": "text", "required": false }
]
}
}'Example — fire an event
curl -X POST https://api.shopimind.com/v1/events/trigger/store_purchase \
-H "spm-api-key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"contact": { "email": "marie.dupont@example.com" },
"metaData": {
"order_id": 12345,
"total_amount": 89.50,
"store_code": "PAR-13"
}
}'Validation on trigger
triggerEvent validates each payload against the declared schema. The call is rejected with 400 if:
- a field marked
required: trueis missing; - a field has a type that doesn't match the declared one;
- a field not declared in the schema is present (strict validation).
Errors are accumulated and returned in a single batch:
{
"statusCode": 400,
"success": false,
"errors": [
"Missing required property: metaData.total_amount",
"Invalid type for property: metaData.order_id. Expected number, got string"
]
}Trigger history
Every emission is logged and queryable via listEventHistories. Each row contains the code_name, the target, the serialized payload and the execution status. Use this first to diagnose a scenario that isn't firing as expected.
Typical use cases
- POS / cash register — fire a "physical store purchase" event to unify post-purchase workflows across web and retail (recovery, loyalty, satisfaction).
- Loyalty program — fire
loyalty.points_earned,loyalty.tier_upgradedorloyalty.points_expiringevents from your loyalty engine to trigger real-time scenarios (thank-you, tier unlocked, expiration reminder). Details: Tiered loyalty program. - Carrier webhook — fire a "delivered" event to trigger a review request 2 to 4 days after actual receipt (vs. shipping).
- ERP — fire a "subscription renewed" or "unpaid invoice detected" event to wire marketing follow-up to your operational events.
See also the detailed use cases combining external events and custom data.
Coming soon — outbound action webhooks
Today the API only exposes the inbound direction: your third-party system fires an event, ShopiMind executes the subscribed scenarios.
Outbound action webhooks — where ShopiMind notifies an external system (CRM, ERP, data warehouse) via a signed POST to a URL you provide whenever a scenario action fires — are being finalized and will be available shortly.
Limits and gotchas
- Strict validation — any field not declared in the
propertiesschema is rejected. Remember to update the event type (updateEvent) before sending a new field. - Async by design —
triggerEventreturns before the scenario executes. For reliable triggering, monitorlistEventHistoriesrather than the HTTP response of the call. code_namebreaks the URL — renaming acode_nameimmediately changes thetriggerEventpath. Running scenarios aren't affected, but third-party emitters must be updated.- Permanent deletion —
deleteEventis irreversible and stops subscribed scenarios. For a reversible pause, remove the subscription on the scenario side from the dashboard.
API reference
createEvent · updateEvent · listEvents · getEvent · deleteEvent · triggerEvent · listEventHistories.