Webhook Events
Complete reference of all available events in Sarah's webhooks
Last updated: 2025-01-26
This is the complete reference of all events supported in Sarah's webhooks, both for inbound and outbound.
Available Events
Sales
sales.created
Triggered when a new sale is created.
Structure:
json{
"event": "sales.created",
"data": {
"sale": {
"id": 789,
"company_id": 42,
"customer_id": 123,
"box_id": 5,
"total": 15000.00,
"status": "pending",
"payment_method": "cash",
"items": [
{
"id": 1,
"product_id": 456,
"quantity": 2,
"price": 7500.00,
"subtotal": 15000.00
}
],
"created_at": "2025-01-26T12:34:56.789Z"
}
}
}
Main fields:
id: Unique sale IDcompany_id: Company IDcustomer_id: Customer ID (can be null)box_id: Cash register IDtotal: Sale totalstatus: Status (pending,paid,cancelled)payment_method: Payment methoditems: Array of sale items
sales.paid
Triggered when a sale is marked as paid.
Structure:
json{
"event": "sales.paid",
"data": {
"sale": {
"id": 789,
"company_id": 42,
"total": 15000.00,
"status": "paid",
"paid_at": "2025-01-26T12:35:00.000Z",
"payment_method": "mercadopago",
"payment_id": "mp_payment_123"
}
}
}
sales.cancelled
Triggered when a sale is canceled.
Structure:
json{
"event": "sales.cancelled",
"data": {
"sale": {
"id": 789,
"company_id": 42,
"status": "cancelled",
"cancelled_at": "2025-01-26T12:36:00.000Z",
"cancellation_reason": "Customer requested cancellation"
}
}
}
Billing
invoice.issued
Triggered when an electronic fiscal receipt (AFIP/ARCA) is issued.
Structure:
json{
"event": "invoice.issued",
"data": {
"invoice": {
"id": 101,
"company_id": 42,
"sale_id": 789,
"type": "A",
"point_of_sale": 1,
"number": 12345,
"cae": "12345678901234",
"cae_expiration": "2025-02-26T00:00:00.000Z",
"total": 18150.00,
"issued_at": "2025-01-26T12:37:00.000Z"
}
}
}
Main fields:
type: Receipt type (A,B,C, etc.)point_of_sale: Point of salenumber: Receipt numbercae: Electronic Authorization Codecae_expiration: CAE expiration date
Inventory
movement.created
Triggered when an inventory movement is created (entry, exit, transfer, etc.).
Structure:
json{
"event": "movement.created",
"data": {
"movement": {
"id": 555,
"company_id": 42,
"type": "IN",
"deposit_id": 10,
"product_id": 456,
"amount": 10,
"reason": "Purchase",
"created_at": "2025-01-26T12:38:00.000Z"
}
}
}
Movement types:
IN: Stock entryOUT: Stock exitTRANSFER: Transfer between warehousesADJUSTMENT: Inventory adjustment
product.upserted
Triggered when a product is created or updated.
Structure:
json{
"event": "product.upserted",
"data": {
"product": {
"id": 123,
"company_id": 42,
"sku": "ABC-001",
"name": "Example Product",
"description": "Product description",
"base_price": 1500.00,
"stock": 40,
"category_id": 5,
"mark": "Example Brand",
"enable": true,
"photo": "https://example.com/photo.jpg",
"updated_at": "2025-01-26T12:39:00.000Z"
}
}
}
Note: This event is triggered both on creation and update. Use updated_at to determine if it's new or updated.
product.stock_updated
Triggered when a product's stock changes.
Structure:
json{
"event": "product.stock_updated",
"data": {
"product": {
"id": 123,
"company_id": 42,
"sku": "ABC-001",
"previous_stock": 50,
"current_stock": 40,
"change": -10,
"deposit_id": 10,
"updated_at": "2025-01-26T12:40:00.000Z"
}
}
}
Usage in Inbound
When sending events to Sarah (inbound), you must follow the exact structure shown above. Sarah will validate:
- That the event is in the list of supported events
- That the
datastructure is correct according to event type - That required fields are present
Inbound Send Example
httpPOST /api/integration/in
Authorization: Bearer sk_live_abc123...
Content-Type: application/json
x-idempotency-key: product.upserted:123
{
"event": "product.upserted",
"data": {
"product": {
"id": 123,
"sku": "ABC-001",
"name": "Updated Product",
"base_price": 1600.00,
"stock": 45
}
}
}
Usage in Outbound
When receiving events from Sarah (outbound), events will follow the same structure. You can use fields to:
- Trigger actions: Execute workflows in Make/Zapier
- Sync data: Update external systems
- Notifications: Send alerts or emails
- Analytics: Log events for analysis
Handler Example
javascriptexport async function POST(request) {
const { event, data } = await request.json();
switch (event) {
case 'sales.created':
await notifyNewSale(data.sale);
await syncToCRM(data.sale);
break;
case 'product.stock_updated':
if (data.product.current_stock < 10) {
await sendLowStockAlert(data.product);
}
break;
case 'invoice.issued':
await sendInvoiceEmail(data.invoice);
break;
}
return new Response(JSON.stringify({ status: 'ok' }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
}
Extensibility
Sarah is designed to be extensible. In the future new events can be added:
customer.createdcustomer.updateddeposit.createdpromotion.activatedorder.shipped
Unrecognized events are safely ignored (no-op) to maintain forward compatibility.
Best Practices
- Handle all events you might need, even if you don't use them now
- Validate structure before processing
- Use idempotency keys to avoid duplicate processing
- Log events for debugging and auditing
- Handle errors gracefully - don't fail entire webhook due to one problematic event