Event catalog
Every event SKUFlow sends to webhooks, grouped by area, with the fields of its data.
SKUFlow sends 79 kinds of event. Each delivery's body is the event envelope with the fields below in data. Event data carries ids, statuses, amounts and dates only: never names, addresses, notes, secrets or costs. Read the full record with the API when you need it (the record's id is data.recordId).
Subscribe to any of these by name when you create a webhook endpoint, or leave the list empty to receive every event. The same list is available from the API: List event types.
Common to every event:
Field in data | Type | Description |
|---|---|---|
recordId | string | The record the event is about. Its type is the event's prefix: invoice.paid carries an invoice id. |
identifier | string (optional) | The record's number when it has one, such as INV-12 or ORD-4. |
Customers
customer.created
A customer (or lead) was created.
Field in data | Type | Description |
|---|---|---|
type | enum | One of RESIDENTIAL, COMMERCIAL. |
status | string | |
leadSourceId | string (optional) |
customer.updated
A customer's details changed. fields names what changed (never the values).
Field in data | Type | Description |
|---|---|---|
fields | array of string |
portal.link_created
A customer portal link was created or replaced.
Field in data | Type | Description |
|---|---|---|
customerId | string |
portal.session_revoked
A customer's portal session ended early: they signed out, staff signed them out, or sign-in was turned off. recordId is the session.
Field in data | Type | Description |
|---|---|---|
customerId | string | |
reason | enum | One of SIGNED_OUT, STAFF, SIGN_IN_DISABLED, REPLACED. |
portal.signed_in
A customer signed in to their portal with a code or a one-tap email link. recordId is the customer session.
Field in data | Type | Description |
|---|---|---|
customerId | string | |
method | enum | One of EMAIL_CODE, SMS_CODE, EMAIL_LINK. |
portal.viewed
A customer opened their portal.
Field in data | Type | Description |
|---|---|---|
customerId | string |
Requests and quotes
quote.approved
A quote was approved (by the customer, or by staff for them).
Field in data | Type | Description |
|---|---|---|
byStaff | boolean (optional) |
quote.changes_requested
The customer asked for changes to a quote.
Field in data | Type | Description |
|---|
quote.converted
An approved quote became an invoice.
Field in data | Type | Description |
|---|---|---|
invoiceId | string |
quote.created
A quote was created.
Field in data | Type | Description |
|---|
quote.declined
The customer declined a quote.
Field in data | Type | Description |
|---|
quote.sent
A quote was sent to the customer.
Field in data | Type | Description |
|---|
request.archived
A request was archived.
Field in data | Type | Description |
|---|
request.converted
A request became a quote.
Field in data | Type | Description |
|---|---|---|
quoteId | string |
request.created
A request came in (by staff, the online request form or the portal).
Field in data | Type | Description |
|---|---|---|
source | enum | One of MANUAL, ONLINE_BOOKING, PORTAL, DESIGN_STUDIO. |
Invoices
invoice.created
An invoice was created (usually as a draft).
Field in data | Type | Description |
|---|---|---|
customerId | string | |
status | string | |
totalCents | integer | Integer cents. |
dueDate | string (optional) | YYYY-MM-DD in the business's calendar. |
invoice.overdue
An unpaid invoice passed its due date (the scheduler's overdue sweep).
Field in data | Type | Description |
|---|---|---|
customerId | string | |
dueDate | string (optional) | YYYY-MM-DD in the business's calendar. |
balanceDueCents | integer | Integer cents. |
invoice.paid
An invoice was paid in full.
Field in data | Type | Description |
|---|---|---|
amountPaidCents | integer | Integer cents. |
balanceDueCents | integer | Integer cents. |
invoice.partially_paid
A payment left part of an invoice due.
Field in data | Type | Description |
|---|---|---|
amountPaidCents | integer | Integer cents. |
balanceDueCents | integer | Integer cents. |
invoice.sent
An invoice was issued to the customer (status SENT).
Field in data | Type | Description |
|---|---|---|
customerId | string | |
totalCents | integer | Integer cents. |
balanceDueCents | integer | Integer cents. |
dueDate | string (optional) | YYYY-MM-DD in the business's calendar. |
Payments
payment.disputed
A customer's bank opened a dispute (chargeback) on an online payment.
Field in data | Type | Description |
|---|---|---|
invoiceId | string (optional) | |
amountCents | integer | Integer cents. |
status | string | |
reason | string (optional) |
payment.failed
An online payment failed: declined, a bank debit bounced, or the checkout page expired unpaid.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
invoiceId | string (optional) | |
quoteId | string (optional) | |
amountCents | integer | Integer cents. |
tipCents | integer (optional) | Integer cents. |
reason | string | Stripe's code (card_declined, authentication_required…) or checkout_expired / checkout_replaced / bank_debit_failed. |
channel | enum (optional) | One of PORTAL, INVOICE_LINK, QUOTE_PAGE, STAFF, STORE. |
payment.recorded
Money was received: against an invoice, or a quote deposit.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
invoiceId | string (optional) | |
quoteId | string (optional) | |
deposit | boolean (optional) | |
amountCents | integer | Integer cents. |
tipCents | integer (optional) | Integer cents. |
method | enum | One of CASH, CHECK, CARD, BANK_TRANSFER, OTHER. |
notifyCustomer | boolean (optional) | |
processor | enum (optional) | STRIPE for an online payment settled by Stripe; MANUAL (or absent) when staff recorded it. One of MANUAL, STRIPE. |
payment.refunded
A payment was (partly) refunded.
Field in data | Type | Description |
|---|---|---|
refundId | string | |
amountCents | integer | Integer cents. |
invoiceId | string (optional) | |
quoteId | string (optional) |
payments.account_updated
The business's Stripe account changed standing: connected, charges or payouts enabled or paused, details submitted, or disconnected.
Field in data | Type | Description |
|---|---|---|
state | enum | One of NOT_CONNECTED, ONBOARDING, RESTRICTED, ACTIVE. |
chargesEnabled | boolean | |
payoutsEnabled | boolean | |
detailsSubmitted | boolean |
Team
chat.message_sent
Someone wrote in team chat (the team or a direct message).
Field in data | Type | Description |
|---|---|---|
conversationId | string | |
kind | enum | One of TEAM, DIRECT. |
Inventory and purchasing
inventory.low_stock
An item reached its reorder point at a location.
Field in data | Type | Description |
|---|---|---|
locationId | string | |
onHand | number | |
reorderPoint | number (optional) |
inventory.negative_stock
An item went below zero at a location.
Field in data | Type | Description |
|---|---|---|
locationId | string | |
onHand | number | |
reorderPoint | number (optional) |
inventory.transferred
Stock moved between locations.
Field in data | Type | Description |
|---|---|---|
fromLocationId | string | |
toLocationId | string | |
lines | integer |
pricebook.imported
A pricebook CSV was imported.
Field in data | Type | Description |
|---|---|---|
created | integer | |
updated | integer |
purchase_order.cancelled
A purchase order was cancelled.
Field in data | Type | Description |
|---|
purchase_order.received
Items on a purchase order were received.
Field in data | Type | Description |
|---|---|---|
status | string | |
lines | integer |
purchase_order.sent
A purchase order was sent to its vendor.
Field in data | Type | Description |
|---|---|---|
vendorId | string |
Messages and automations
automation.disabled
An automation (engagement rule) was turned off.
Field in data | Type | Description |
|---|---|---|
presetKey | string (optional) | |
triggerType | enum | One of EVENT, SCHEDULE, ABSENCE, RELATIVE. |
automation.enabled
An automation (engagement rule) was turned on.
Field in data | Type | Description |
|---|---|---|
presetKey | string (optional) | |
triggerType | enum | One of EVENT, SCHEDULE, ABSENCE, RELATIVE. |
consent.changed
A contact method's messaging consent changed (STOP / START reply, the unsubscribe page, staff, a bounce).
Field in data | Type | Description |
|---|---|---|
customerId | string | |
channel | enum | One of EMAIL, SMS. |
purpose | enum | One of TRANSACTIONAL, MARKETING. |
status | enum | One of OPTED_IN, OPTED_OUT. |
source | string | reply:STOP, reply:START, unsubscribe-page, staff, bounce, complaint. |
message.bounced
An email bounced or was marked as spam; its address is suppressed.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
channel | enum | One of EMAIL, SMS. |
kind | enum | One of BOUNCE, COMPLAINT. |
message.delivered
The provider confirmed a message was delivered.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
channel | enum | One of EMAIL, SMS. |
ruleId | string (optional) |
message.failed
A message could not be sent (the provider refused it).
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
channel | enum | One of EMAIL, SMS. |
ruleId | string (optional) | |
reason | string | A short code: provider_error, provider_not_configured … |
message.replied
A customer replied to a text (logged as an inbound message). Ends cadences that list it as an exit.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
channel | enum | One of EMAIL, SMS. |
inReplyToId | string (optional) | |
keyword | enum (optional) | Set when the reply was an opt-out, opt-in or help keyword. One of STOP, START, HELP. |
message.sent
A customer email or text was sent (or, in test mode, rendered and logged as SENT_TEST).
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
channel | enum | One of EMAIL, SMS. |
purpose | enum | One of TRANSACTIONAL, MARKETING. |
source | enum | One of AUTOMATION, MANUAL, TEST, INBOUND, CAMPAIGN, SYSTEM. |
status | enum | One of SENT, SENT_TEST. |
ruleId | string (optional) | |
subjectType | string (optional) | |
subjectId | string (optional) | |
campaignId | string (optional) |
Marketing
campaign.cancelled
A campaign was cancelled before it finished.
Field in data | Type | Description |
|---|---|---|
channels | array of enum | |
status | enum | One of DRAFT, SCHEDULED, SENDING, PAUSED, SENT, CANCELLED. |
campaign.completed
Every recipient of a campaign was handled (queued, or skipped with the reason).
Field in data | Type | Description |
|---|---|---|
channels | array of enum | |
status | enum | One of DRAFT, SCHEDULED, SENDING, PAUSED, SENT, CANCELLED. |
queued | integer | |
skipped | integer |
campaign.paused
A sending or scheduled campaign was paused.
Field in data | Type | Description |
|---|---|---|
channels | array of enum | |
status | enum | One of DRAFT, SCHEDULED, SENDING, PAUSED, SENT, CANCELLED. |
campaign.resumed
A paused campaign was resumed.
Field in data | Type | Description |
|---|---|---|
channels | array of enum | |
status | enum | One of DRAFT, SCHEDULED, SENDING, PAUSED, SENT, CANCELLED. |
campaign.scheduled
A marketing campaign was scheduled for later (a time, or each recipient's local time).
Field in data | Type | Description |
|---|---|---|
channels | array of enum | |
status | enum | One of DRAFT, SCHEDULED, SENDING, PAUSED, SENT, CANCELLED. |
audienceCount | integer |
campaign.started
A marketing campaign started sending.
Field in data | Type | Description |
|---|---|---|
channels | array of enum | |
status | enum | One of DRAFT, SCHEDULED, SENDING, PAUSED, SENT, CANCELLED. |
audienceCount | integer |
referral.converted
A referred customer converted (first paid invoice by default); the referrer's reward was issued unless the cap withheld it.
Field in data | Type | Description |
|---|---|---|
referrerCustomerId | string | |
referredCustomerId | string | |
rewardWithheld | boolean |
referral.created
Someone came in through a customer's referral link, or staff recorded a referral.
Field in data | Type | Description |
|---|---|---|
referrerCustomerId | string | |
referredCustomerId | string (optional) | |
requestId | string (optional) | |
source | enum | One of LINK, STAFF. |
referral.rejected
A referral was refused: self-referral, an existing customer, or by staff.
Field in data | Type | Description |
|---|---|---|
referrerCustomerId | string | |
reason | enum | One of SELF_REFERRAL, EXISTING_CUSTOMER, DUPLICATE, STAFF. |
referral.reward_applied
A referral reward was used: a credit line on an invoice, or the gift card was sent.
Field in data | Type | Description |
|---|---|---|
referralId | string | |
customerId | string | |
invoiceId | string (optional) | |
amountCents | integer | Integer cents. |
referral.reward_issued
A referral reward was earned.
Field in data | Type | Description |
|---|---|---|
referralId | string | |
customerId | string | |
party | enum | One of REFERRER, FRIEND. |
kind | enum | One of ACCOUNT_CREDIT, DISCOUNT, GIFT_CARD, NONE. |
amountCents | integer | Integer cents. |
Website
website.deleted
The business's website was deleted with its pages, addresses and stats (the image library stays).
Field in data | Type | Description |
|---|---|---|
subdomain | string | |
wasPublished | boolean |
website.domain_activated
A custom domain passed its DNS checks and now serves the website.
Field in data | Type | Description |
|---|---|---|
hostname | string |
website.published
The business's website was published (or republished).
Field in data | Type | Description |
|---|---|---|
pageCount | integer |
website.unpublished
The business's website was taken down.
Field in data | Type | Description |
|---|
Online stores
store.closed
An online store was closed: it takes no more orders and its production batch is final.
Field in data | Type | Description |
|---|---|---|
orderCount | integer | |
unitCount | integer |
store.domain_activated
A custom domain passed its DNS checks and now serves the online store.
Field in data | Type | Description |
|---|---|---|
hostname | string |
store.published
An online store was opened for orders (or reopened).
Field in data | Type | Description |
|---|---|---|
kind | enum | One of COMPANY, TEAM, FUNDRAISER, RETAIL. |
customerId | string (optional) |
store_order.approved
A company-paid store order was approved.
Field in data | Type | Description |
|---|---|---|
storeId | string |
store_order.cancelled
A store order was cancelled (by staff, or its online payment never arrived).
Field in data | Type | Description |
|---|---|---|
storeId | string | |
reason | string |
store_order.fulfilled
A store order was handed over or shipped.
Field in data | Type | Description |
|---|---|---|
storeId | string |
store_order.paid
A store order's online payment arrived; it is PLACED.
Field in data | Type | Description |
|---|---|---|
storeId | string | |
invoiceId | string (optional) | |
totalCents | integer | Integer cents. |
store_order.placed
A store order was placed: PENDING_PAYMENT (paying online), AWAITING_APPROVAL (company-paid) or PLACED.
Field in data | Type | Description |
|---|---|---|
storeId | string | |
customerId | string (optional) | |
invoiceId | string (optional) | |
status | string | |
checkoutMode | enum | One of PAY_ONLINE, INVOICE_ACCOUNT, FREE. |
totalCents | integer | Integer cents. |
store_order.rejected
A company-paid store order was not approved.
Field in data | Type | Description |
|---|---|---|
storeId | string |
Orders and production
order.created
An order (ORD-n) was made from a quote, an invoice, a store's batch or by hand.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
source | enum | One of QUOTE, INVOICE, STORE, MANUAL. |
dueDate | string (optional) | YYYY-MM-DD in the business's calendar. |
order.status_changed
An order moved: waiting on art, payment or goods, ready, in production, ready to ship, shipped, completed, on hold or cancelled.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
from | enum | One of AWAITING_ART, AWAITING_PAYMENT, AWAITING_GOODS, READY, IN_PRODUCTION, READY_TO_SHIP, SHIPPED, COMPLETED, ON_HOLD, CANCELLED. |
to | enum | One of AWAITING_ART, AWAITING_PAYMENT, AWAITING_GOODS, READY, IN_PRODUCTION, READY_TO_SHIP, SHIPPED, COMPLETED, ON_HOLD, CANCELLED. |
shipment.delivered
The carrier delivered the package.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
orderId | string (optional) | The order it ships. |
storeOrderId | string (optional) | Or the store order it ships. |
carrier | string (optional) |
shipment.exception
The package was returned to the sender or could not be delivered.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
orderId | string (optional) | |
storeOrderId | string (optional) | |
carrier | string (optional) | |
status | enum | One of RETURNED, FAILURE. |
shipment.label_created
A shipping label was bought for an order or a store order.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
orderId | string (optional) | The order it ships. |
storeOrderId | string (optional) | Or the store order it ships. |
carrier | string (optional) |
shipment.shipped
The carrier has the package: it is on its way.
Field in data | Type | Description |
|---|---|---|
customerId | string (optional) | |
orderId | string (optional) | The order it ships. |
storeOrderId | string (optional) | Or the store order it ships. |
carrier | string (optional) |
Reviews
feedback.submitted
A customer rated their order when paying (stars and a comment, kept in SKUFlow). Low ratings are worth a call.
Field in data | Type | Description |
|---|---|---|
rating | integer | 1–5 stars. |
customerId | string | |
invoiceId | string |
review.received
A new Google review arrived (synced from the Business Profile). Low ratings are worth a quick reply.
Field in data | Type | Description |
|---|---|---|
rating | integer | 1–5 stars. |
locationId | string | |
customerId | string (optional) | The customer it was matched to by name, if one. |
review.replied
The business replied publicly to a Google review.
Field in data | Type | Description |
|---|---|---|
rating | integer |
Phone
call.completed
A call ended: answered (COMPLETED), MISSED, VOICEMAIL or, for an outbound call, FAILED.
Field in data | Type | Description |
|---|---|---|
direction | enum | One of INBOUND, OUTBOUND. |
status | enum | One of COMPLETED, MISSED, VOICEMAIL, FAILED. |
source | enum (optional) | One of MAIN, WEBSITE, GOOGLE_BUSINESS, CAMPAIGN, QR_CODE, BUSINESS_UNIT, PRINT, OTHER. |
phoneNumberId | string (optional) | |
customerId | string (optional) | |
durationSeconds | integer (optional) |
call.received
An inbound call reached one of the business's numbers (before anyone answered).
Field in data | Type | Description |
|---|---|---|
direction | enum | One of INBOUND, OUTBOUND. |
source | enum (optional) | One of MAIN, WEBSITE, GOOGLE_BUSINESS, CAMPAIGN, QR_CODE, BUSINESS_UNIT, PRINT, OTHER. |
phoneNumberId | string (optional) | |
customerId | string (optional) | |
afterHours | boolean |
System
billing.addon_acknowledged
An owner accepted a paid add-on's usage terms (adding it, turning on SKUFlow-managed telephony, or after a price change). recordId is the acknowledgement.
Field in data | Type | Description |
|---|---|---|
addonKey | string | |
context | enum | One of ADD_ADDON, MANAGED_TELEPHONY, REVIEW. |
priceVersion | string | |
userId | string |
import.completed
A migration import finished. The only event of an import: its records emit no events of their own. recordId is the import run.
Field in data | Type | Description |
|---|---|---|
source | enum | One of DECONETWORK, SPREADSHEET. |
created | integer | |
updated | integer |
webhook.test
A test event sent from Settings → Developers → Webhooks to one endpoint only. Sent only by Send test event; you cannot subscribe to it.
Field in data | Type | Description |
|---|---|---|
message | string |