Skip to content

Store webhooks

Your store tells your server what happens in it through webhooks: an order placed, a parcel delivered, a return asked for, a site published. Each event is signed with Tuppence-Signature like every other, and carries the object as the API shows it.

Choose the events when you add an endpoint: in the dashboard under Developers › Webhooks, where they are grouped under Store, or with enabled_events on POST /v1/webhook_endpoints.

Terminal window
curl -sS https://api.tuppence.ai/v1/webhook_endpoints \
-H "Authorization: Bearer $TUPPENCE_SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/hooks/tuppence",
"enabled_events": ["order.created", "store.order_placed", "shipment.delivered"]}'

An order from your store is an ordinary order: order.created carries it with source: "online", then order.paid and order.completed. store.order_placed follows with the store’s own view: its number, site, checkout and fulfilment.

Every store event has its payload model in the API reference (x-webhooks), with an example, and the SDKs know them all: narrow on type and data.object is that event’s object.

import { constructEvent, type StoreEvent } from "@tuppence/node";
const event = constructEvent<StoreEvent>(rawBody, req.headers["tuppence-signature"], secret);
if (event.type === "order.created") {
console.log(event.data.object.source, event.data.object.totals.total);
}
from tuppence import construct_store_event, models
event = construct_store_event(raw_body, request.headers["Tuppence-Signature"], secret)
if isinstance(event.root, models.OrderCreatedEvent):
print(event.root.data.object.source)

A platform’s endpoint with connect: true hears the stores of its connected businesses: the same events, each with account naming the business. See Connect: your connected accounts’ events.

GroupEventsWhen
Sitestore.site_updated, store.site_published, store.site_reverted, store.site_scheduledThe site changed, a version went live, an earlier one went back live, a publish was scheduled
store.domain_requested, store.domain_active, store.domain_failed, store.domain_removed, store.domain_switchedYour own domain: asked for, working, not working, removed, switched
merchant_sending_domain.verifiedYour own sending domain verified: store emails go from it from now on
store.proposal_started, store.proposal_ready, store.proposal_failed, store.proposal_publishedThe store builder’s proposal for a site
store.snap_started, store.snap_ready, store.snap_failed, store.snap_publishedA product made from photos taken in the app
store.import_started, store.import_completed, store.import_undoneAn import from another platform
Catalogueproduct.created, product.updated, product.archivedA product, at the till and online
store.product_published, store.product_unpublishedA product put online, or taken off
store.collection_created, store.collection_updated, store.collection_deletedA collection
store.drop_created, store.drop_updatedA drop and its queue
stock.available, stock_alert.sent, stock_movement.createdBack in stock, a back-in-stock alert sent, any stock change
Ordersstore.order_placedA store order, with its number, site, checkout and fulfilment
order.created, order.updated, order.paid, order.completed, tender.createdThe order itself, with source
store.checkout_abandoned, store.cancellation_receivedA checkout left unpaid; a shopper cancelling within their rights
subscription.renewal_skipped, subscription.renewal_notice_sentSubscribe and save: a renewal skipped, a shopper told of a higher price
Deliveryfulfilment.shipped, fulfilment.delayedA parcel left; one is late
shipment.updated, shipment.in_transit, shipment.out_for_delivery, shipment.available_for_pickup, shipment.delivered, shipment.exception, shipment.returned_to_senderThe carrier’s news, every change and which change it was
Returnsreturn.requested, return.approved, return.rejected, return.received, return.refunded, return.closedA return, from asking to closed
return.refund_due_soonA refund the law wants within 14 days is still owed on day 10
Channelsstore.channel_connected, store.channel_updated, store.channel_disconnected, store.channel_errorA sales channel, such as a marketplace
listing.live, listing.rejected, listing.removed, listing.restrictedA product’s listing on a channel
AI agentsstore.agent_settings.updatedA switch on Store › AI channels changed: an assistant shown or hidden, its checkout or its most, hidden products
store.agent.blocked, store.agent.unblockedA shopper’s agent paused at your store (card testing, scraping, resale, or by Tuppence), and the pause lifted
Shoppersreview.created, review.repliedA review of the business, and your reply
product_review.requested, product_review.published, product_review.rejectedA product review: asked for, published, rejected
store_thread.message_received, store_thread.needs_youAsk the shop: a shopper wrote; a thread needs a person
store.privacy_request_receivedA shopper asked for their data or its deletion
store_flow.pausedAn email flow paused itself: too many unsubscribes or complaints for its sends
Assistantchange_set.applied, change_set.reverted, change_set.proposed, change_set.declined, change_set.expiredA change set: made, undone, waiting for a person, declined, past its time
assistant_job.updated, assistant_job.paused, job_run.finishedOne of the assistant’s jobs, and each of its runs
store_brief.readyThe morning brief is written
Rulesstore.tax_threshold_near, store.tax_threshold_reached, tax_registration.createdUS sales tax thresholds, and a registration recorded
policy.version_drafted, policy.version_publishedYour store’s policies

No event carries a shopper’s card, a label’s file, a token or a thread’s words.

Docs assistant

Open as a page
Loading the assistant…