Event reference
The event types Soxara emits today. This list is deliberately short — we only document events that actually fire, so you never subscribe to something that never arrives. More land here as they ship.
Payment events
| Event | When it fires |
|---|---|
payment.completed | A payment settled — a payment-link payment cleared, or a recurring charge succeeded. Funds are credited to your merchant wallet. |
payment.failed | A payment did not settle — card declined, MoMo timed out / cancelled, insufficient wallet balance, or an expired link. No funds moved. |
(Internally, a link that expires also emits payment.failed — you reconcile on “did the money
land?”, not the specific failure mode.)
These fire for every payment path: hosted-checkout link payments, sandbox
simulate calls, and recurring
mandate charges — all the same two events, same shape.
Payroll events
Fire once a payroll run reaches a terminal state — for a run created from the dashboard or via the API alike.
| Event | When it fires |
|---|---|
payroll_run.completed | Every payment in the run succeeded. |
payroll_run.partial | Some payments succeeded, some didn’t (a bad phone match, insufficient wallet balance, etc.) — check data.payments for which. |
payroll_run.failed | No payment in the run succeeded. |
{
"type": "payroll_run.completed",
"createdAt": "2026-09-10T09:00:00Z",
"data": {
"run": { "id": "…", "merchant_id": "…", "status": "completed", "currency": "USD", "…": "…" },
"payments": [
{ "external_ref": "emp-1029", "payee_label": "Adama Smith", "status": "completed", "amount": 150000, "…": "…" }
]
}
}Correlate on data.payments[].external_ref — the id you sent when creating each line.
Catalog events
| Event | When it fires |
|---|---|
catalog.published | A catalog version is published — fires once per publish with the full version snapshot, not per item edit. Draft edits never fire this. |
{
"type": "catalog.published",
"createdAt": "2026-09-10T09:00:00Z",
"data": {
"catalog_id": "…",
"version_id": "…",
"published_at": "2026-09-10T09:00:00Z",
"snapshot": { /* the same shape your public catalog read returns */ }
}
}Your integration can re-sync its whole catalog from data.snapshot on each delivery — there’s no
partial/delta version to reconcile.
Inventory events
| Event | When it fires |
|---|---|
inventory.low_stock | An item’s quantity crosses at or below its low-stock threshold. Fires once per crossing, not on every movement — recovering above the threshold does not fire a symmetric “restocked” event yet. |
{
"type": "inventory.low_stock",
"createdAt": "2026-09-10T09:00:00Z",
"data": {
"item_id": "…",
"name": "House Blend, 1kg",
"sku": "HB-1KG",
"current_qty": "4",
"low_stock_threshold": "10",
"unit": "bag"
}
}Treat this as a “go re-check this item” nudge, not a live, authoritative running total — poll the item’s own read endpoint if you need the current count.
Payload (payment events)
payment.completed/payment.failed share one shape (see Overview
for the full field table):
{
"type": "payment.completed",
"createdAt": "2026-07-04T18:00:00Z",
"data": {
"payment": {
"id": "…",
"amount": 1200,
"currency": "USD",
"status": "completed",
"payment_method": "card",
"environment": "test",
"mandate_id": "…", // set on a recurring charge; null for a link payment
"payment_link_id": null, // set on a link payment; null for a charge
"idempotency_key": "sub_42:2026-07", // your key — the correlation handle
"created_at": "…"
},
"link": { … } // a snapshot of the payment link, when the payment is link-bound
}
}Correlating an event back to your records
- Recurring charges: match on
data.payment.idempotency_key(the cycle key you sent onPOST /v1/api/charges) ordata.payment.mandate_id. - Payment links: match on
data.link.id/data.link.link_code, or the idempotency key you set at link creation.
Coming later
Refunds, disputes, and richer lifecycle events will appear here when they’re actually emitted — not before. If your integration needs one that isn’t listed, tell us at [email protected] so we prioritise it.