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 as YYYY-MM-DD: the string can go straight into the from parameter 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, call GET /schedule-entries with a month-long range starting at month.

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"
  }
}
  • actioncreated, updated or deleted.
  • entry_id — the schedule row id; it matches id in the GET /schedule-entries response.
  • 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-DD in the organization timezone.
  • related is absent when action is deleted: the row is gone and the request would return an empty list. entry_id is 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"
  }
}
  • kindin (arrival) or out (departure).
  • check_in_id — the check-in row id; it matches id in the GET /check-ins response. Arrival and departure of the same day share one row, so a pair of events carries the same check_in_id but different Smengo-Event-Id.
  • The exact times are not in the body: read check_in_at / check_out_at through related.

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"
  }
}
  • decisionapproved or rejected. 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 to schedule_entry.changed.
  • Technical updates of a decided request (a notification flag, for example) produce no events — only the status transition to approved/rejected does.

Next

Was this article helpful?