Reactions are configured to react to a specific event and trigger an action whenever that event is processed by the event reactor. An example could be sending a confirmation email to a customer when an order has been successfully placed.
It is not possible for a Reaction to trigger on an event that has happened in the past. Reactions are always configured to listen to events from the moment when the Reaction is configured.
Each reaction is configured with a specific Action that defines what will happen when the reaction is triggered. When a Reaction is triggered it will execute its configured Action.
Currently Serialized offer four pre-defined action types, for Slack, IFTTT, Automate and Zapier, and a generic HTTP action for any system capable of receiving HTTP POST:s.
The action type (HTTP_POST
) requires the field targetUri
to be populated with the address that should receive the POST request. Optionally the field httpHeaders
can be set, i.e. to handle Basic Authentication etc.
All outgoing HTTP request will automatically be HMAC signed using the reaction name as the signing key. To provide your own signing secret, include the field signingSecret
in the action payload.
The reaction requests are HTTP POST requests with a JSON body. The JSON has the following format:
{"metadata":{"aggregateId":"<some-aggregate-id>","timestamp": <epoc-millis>,"sequenceNumber": <n>},"event":{"eventId":"<some-event-id>","eventType":"<event-type>","data":{"key":"value","key":"value",...}}}
As the end-point specified in the targetUri
must be exposed to the public internet it should be protected. Currently it’s possible to utilize Basic Authentication and include the appropriate HTTP header in the Reaction definition.
{"reactionName": "notify-on-order-shipped","feedName": "order","reactOnEventType": "OrderShippedEvent","action": {"actionType": "HTTP_POST","targetUri": "https://your-service","signingSecret": "my-optional-signing-key","httpHeaders": {"Authorization": "Basic c2VasXlZdyW2dGsONfM5fD4adleRDgVbDNgRkgFgZUpgoxgNHdsg15QktFcm1ndjI="}}}
The action type (SLACK_POST
) requires the field targetUri
to be populated with a valid Slack webhook URI. The message text is specified in the field body
. Simple templating is supported and event data can be accessed using dot (.) notation.
Example of a Reaction posting a notification to Slack:
{"reactionName": "on-order-placed-slack-notifier","feedName": "order","reactOnEventType": "OrderPlacedEvent","action": {"actionType": "SLACK_POST","targetUri": "https://hooks.slack.com/services/T0000/B0000/XXXX","body": "A new order with number ${event.data.orderNumber} was placed by ${event.data.customer.email}!"}}
Given this event:
{"eventId": "ca37d05c-a852-4de5-961f-16fb35e8cd7b","eventType": "OrderPlacedEvent","data": {"orderNumber": "12312345","customer": {"email": "customer@example.com"}}}
the message to Slack will look like this:
A new order with number 12312345 was placed by customer@example.com!
The action type (IFTTT_POST
) requires the field targetUri
to be populated with a valid IFTTT webhook URI (i.e. starting with https://maker.ifttt.com/trigger
). The map valueMap
is used for storing the (up to three) dynamic values supported by IFTTT. Simple templating is supported and event data can be accessed using dot (.) notation.
Example of a Reaction posting a request to IFTTT:
{"reactionName": "ifttt-payment-notifier","feedName": "payment","reactOnEventType": "CaptureCompleted","action": {"actionType": "IFTTT_POST","targetUri": "https://maker.ifttt.com/trigger/payment_notification/with/key/<your-key>","valueMap": {"value1": "Payment made by ${event.data.customerId} with amount ${event.data.amount}.","value2": "Some more data","value3": "Even more..."}}}
Given this event:
{"eventId": "ca37d05c-a852-4de5-961f-16fb35e8cd7b","eventType": "CaptureCompleted","data": {"customerId": "some-test-id-1","amount": 12345}}
the request body POST:ed to IFTTT would look like this:
{"value1": "Payment made by some-test-id-1 with amount 12345.","value2": "Some more data","value3": "Even more..."}
The action type (AUTOMATE_POST
) requires the field targetUri
to be populated with a valid Automate.io webhook URI (i.e. starting with https://wh.automate.io/webhook
). The map valueMap
is used for storing the (up to nine) dynamic values. Simple templating is supported and event data can be accessed using dot (.) notation.
Example of a Reaction posting a request to Automate.io:
{"reactionName": "automate-payment-notifier","feedName": "payment","reactOnEventType": "CaptureCompleted","action": {"actionType": "AUTOMATE_POST","targetUri": "https://wh.automate.io/webhook/<your-key>","valueMap": {"value1": "Payment made by ${event.data.customerId} with amount ${event.data.amount}.",..."value9": "Some more data"}}}
Given this event:
{"eventId": "ca37d05c-a852-4de5-961f-16fb35e8cd7b","eventType": "CaptureCompleted","data": {"customerId": "some-test-id-1","amount": 12345}}
the request body POST:ed to Automate.io would look like this:
{"value1": "Payment made by some-test-id-1 with amount 12345.",..."value9": "Some more data"}
The action type (ZAPIER_POST
) requires the field targetUri
to be populated with a valid Zapier webhook URI (i.e. starting with https://hooks.zapier.com/hooks
). The map valueMap
is used for storing the (up to nine) dynamic values. Simple templating is supported and event data can be accessed using dot (.) notation.
Example of a Reaction posting a request to Automate.io:
{"reactionName": "zapier-payment-notifier","feedName": "payment","reactOnEventType": "CaptureCompleted","action": {"actionType": "ZAPIER_POST","targetUri": "https://hooks.zapier.com/hooks/catch/<your-key>","valueMap": {"value1": "Payment made by ${event.data.customerId} with amount ${event.data.amount}.",..."value9": "Some more data"}}}
Given this event:
{"eventId": "ca37d05c-a852-4de5-961f-16fb35e8cd7b","eventType": "CaptureCompleted","data": {"customerId": "some-test-id-1","amount": 12345}}
the request body POST:ed to Zapier would look like this:
{"value1": "Payment made by some-test-id-1 with amount 12345.",..."value9": "Some more data"}
Serialized Reactions have a built-in retry mechanism and will be retried several times over the course of a day. A 2xx
response is required for success, whereas a 4xx
or 5xx
response will be treated as an error and retried.
You can see all retries and any errors for your executed reactions in the Serialized Console.