Reacting to Events

6 views Markdown

Nothing is pushed to your integration, so you either ask again or run your own code where the event happens.

Overview

There is no webhook delivery. That is a deliberate boundary. The installation never holds a queue of your endpoints and never retries against them. It also never leaks work to an address it cannot verify.

Two approaches replace it, and they answer different questions.

Ask again Call a list endpoint on a schedule and act on what changed. Needs nothing but a key, works from anywhere, and lags by however long your interval is.
Be there when it happens Register a listener on a hook and your code runs inside the request that caused the event. Immediate and exact, and it requires code installed on the server.

Choose by where your code can live. An integration outside the installation polls. A module, an add-on or a theme shipped with the installation listens.

Prerequisites

  • For the listener route: somewhere to put PHP inside the installation, which in practice means a module of your own.
  • The exact name of the hook you want. Names are catalogued, and one that does not exist fails quietly.

Walkthrough

Pick the Hook

  1. Find the moment you care about in the hook catalogue, in the Hooks section of this documentation.
  2. Read its parameter list and its mechanism. Some hooks report what happened, others let you change a value, and a third kind can refuse an operation outright.
  3. Note the argument count. Declaring more arguments than the hook sends drops your listener.

Register a Listener

  1. Put a hooks.php in your module and add the listener there.
  2. Keep the body cheap. It runs inside somebody's request, and slow work there is felt by the person waiting.
  3. Hand anything slow to a queue, a file or a scheduled task, and let that do the outbound call.

Verify It Runs

  1. Trigger the event once for real and confirm your side saw it.
  2. If nothing happened, look in the error log before touching the code. One message reports a listener that ran and threw. Another reports a listener whose class or method name could not be resolved.
  3. Neither message means the hook name itself is wrong, or the listener returned nothing on purpose.

Example

This listener reacts to a new order and reads it back through the API in the same process. It leaves the outbound call to a queue.

coremio/modules/Addons/AcmeSync/hooks.php
\Hook::add('action:order.created', 10, function (array $order) {
    $id = (int) ($order['id'] ?? 0);
    if (!$id) return;

    // the same resource the HTTP surface exposes, without a key or a round trip
    $full = \WISECP\Api\Kernel::internal('Orders/GetOrder', ['id' => $id]);
    if (isset($full['error'])) return;

    // queue it; do not call your own endpoint from inside someone's checkout
    \Acme\Sync::enqueue('order.created', $full['data']);
});
action:order.created Runs after the order row is written and before the confirmation notification. Receives the order payload merged with its new id. The return is ignored, so the early exits in the listener above only end your own code.
action:invoice.status_changed The counterpart on the money side: fires whenever an invoice moves between states, including into paid. Receives the reloaded invoice, the new status, the previous one and the transition options. The return is ignored.

Pitfalls

A broken listener is skipped, not surfaced

The engine catches whatever a listener throws, writes it to the error log and moves to the next one. The page it happened on carries on as if nothing was registered. So "my code never runs" and "my code fails every time" look identical from the outside. The log is the only place they differ.

A null argument shifts the ones after it

Arguments are bound by position and a null one is skipped, so the next value slides into its place. A listener that declared two arguments can receive the second value in the first slot with no warning at all. Read the catalogue entry for what is actually sent.

Polling has a floor, and it is your rate limit

A one-second poll spends a key's whole minute budget in one minute. Pick an interval your integration can live with and filter server-side so each call stays small. Stop on a 429 instead of tightening the loop.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.