Events
Four events are available in v1. Each arrives in the shared envelope — this page covers only what differs: the contents of data, whether a related link is present, and the permission required to subscribe.
Catalog
| Event | When it fires | data contents |
related |
|---|---|---|---|
schedule.published |
a manager published a month of the schedule | month, published_at |
no |
schedule_entry.changed |
a shift was created, updated or deleted — by any path | action, entry_id, employee_id, entry_date |
yes, except action: "deleted" |
checkin.recorded |
an employee checked in or out via the bot | check_in_id, employee_id, entry_date, kind |
yes |
swap.decided |
a manager approved or rejected a swap request | request_id, employee_id, entry_date, decision |
no |
The service ping event (the Send test event button) is not part of the catalog: you cannot subscribe to it, and it arrives in the same envelope as every other event — with data: {"test": true} inside (see the example).
Permission to subscribe
Subscribing to an event requires the same permission that gates seeing this data in the Smengo UI. The rule mirrors API key scopes: an endpoint's events are a subset of its creator's permissions.
| Event | Permission required of the endpoint creator | The same gate in the app |
|---|---|---|
schedule.published |
View schedule | the /schedule grid |
schedule_entry.changed |
View schedule | the /schedule grid |
checkin.recorded |
Manage employees | the Check-ins section |
swap.decided |
Manage shifts | deciding swap requests |
The Organization settings permission (manage_org) lets you create and delete webhooks but grants no subscription by itself. Unavailable events are disabled in the form, and bypassing the form is rejected at the database level too.
schedule.published
A month of the schedule was published. One publication, one event.
{
"id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"type": "schedule.published",
"created": "2026-07-28T14:03:11.902Z",
"sequence": 10201,
"org_id": "9c1a2e34-5678-4abc-9def-0123456789ab",
"api_version": "v1",
"data": {
"month": "2026-08-01",
"published_at": "2026-07-28T14:03:11.884+00:00"
}
}
month— the first day of the published month asYYYY-MM-DD: the string can go straight into thefromparameter of an API request.published_at— the moment of publication, ISO 8601 with an offset.- No
related: the v1 API has no publications resource. To fetch the contents, callGET /schedule-entrieswith a month-long range starting atmonth.
schedule_entry.changed
A shift was created, updated or deleted — from the grid, by applying a draft, by the bot, or by permanently deleting an employee (a cascade delete produces one deleted per shift).
{
"id": "3f1c8b52-9a4d-4f7e-b2c1-8e5d0a6b4c39",
"type": "schedule_entry.changed",
"created": "2026-08-01T09:15:23.481Z",
"sequence": 10427,
"org_id": "9c1a2e34-5678-4abc-9def-0123456789ab",
"api_version": "v1",
"data": {
"action": "updated",
"employee_id": "5e6d9f2a-3b7c-4e2f-9a1d-7c8e2f6b4a10",
"entry_date": "2026-08-14",
"entry_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
},
"related": {
"url": "https://smengo.com/api/v1/schedule-entries?from=2026-08-14&to=2026-08-14"
}
}
action—created,updatedordeleted.entry_id— the schedule row id; it matchesidin theGET /schedule-entriesresponse.employee_id— the employee after the change: if the shift was reassigned, you get the new one.entry_date— the day of the shift,YYYY-MM-DDin the organization timezone.relatedis absent whenactionisdeleted: the row is gone and the request would return an empty list.entry_idis all you need — delete the row on your side.
Re-saving a shift without changes produces no event: an event is born only when a meaningful field changed (employee, date, status, shift preset, start or end time).
An ordinary employee deletion — the Delete button, which moves the person to the Deleted folder — produces no events at all: the employee card is hidden, while the schedule rows stay where they are. The cascade only fires on Delete permanently from the Deleted folder: there the shift rows really are removed, and each one produces a deleted.
Mind the side effect of an ordinary deletion: no events fire, yet the employee and their shifts disappear from the v1 API — GET /schedule-entries, /check-ins and /timesheets all exclude deleted employees. If you keep your own copy of the schedule, reconcile it against Employees instead of waiting for a deleted that never comes.
A bulk operation — applying a draft or permanently deleting an employee — produces a batch of events: they share the same created and differ by sequence. The batch goes out within about 15 minutes.
checkin.recorded
An employee checked in or out via the Telegram bot.
{
"id": "8d7c6b5a-4e3f-4a2b-9c8d-7e6f5a4b3c2d",
"type": "checkin.recorded",
"created": "2026-08-14T06:02:44.117Z",
"sequence": 10512,
"org_id": "9c1a2e34-5678-4abc-9def-0123456789ab",
"api_version": "v1",
"data": {
"check_in_id": "c3d4e5f6-a7b8-4c9d-8e1f-2a3b4c5d6e7f",
"employee_id": "5e6d9f2a-3b7c-4e2f-9a1d-7c8e2f6b4a10",
"entry_date": "2026-08-14",
"kind": "in"
},
"related": {
"url": "https://smengo.com/api/v1/check-ins?from=2026-08-14&to=2026-08-14"
}
}
kind—in(arrival) orout(departure).check_in_id— the check-in row id; it matchesidin theGET /check-insresponse. Arrival and departure of the same day share one row, so a pair of events carries the samecheck_in_idbut differentSmengo-Event-Id.- The exact times are not in the body: read
check_in_at/check_out_atthroughrelated.
swap.decided
A manager decided on a swap request.
{
"id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
"type": "swap.decided",
"created": "2026-08-10T11:47:02.330Z",
"sequence": 10480,
"org_id": "9c1a2e34-5678-4abc-9def-0123456789ab",
"api_version": "v1",
"data": {
"decision": "approved",
"employee_id": "5e6d9f2a-3b7c-4e2f-9a1d-7c8e2f6b4a10",
"entry_date": "2026-08-16",
"request_id": "f6e5d4c3-b2a1-4f9e-8d7c-6b5a4f3e2d1c"
}
}
decision—approvedorrejected. A request cancelled by the employee is not an event.employee_id— the requester;entry_date— the day of the shift the request is about.- No
related: the v1 API has no swap-requests resource. The effect of an approval shows up in the schedule — if you need the reassignment itself, also subscribe toschedule_entry.changed. - Technical updates of a decided request (a notification flag, for example) produce no events — only the status transition to
approved/rejecteddoes.
Next
- Verifying the signature — a mandatory step before processing an event.
- Retries and failures — what happens when the receiver doesn't answer.