> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.stafflion.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.stafflion.com/_mcp/server.

# Events

Your agency sends an event to Stafflion when a shift you work on changes. Each request carries one event, identified by `event_name`. The endpoint, its schemas, code samples, and examples are in the API tab under **Send events**.

## Flow

1. **`shift_request`**: a clinician asks to work a shift Stafflion published to your agency. Stafflion accepts requests only for shifts it published. Stafflion approves the request by calling your partner API. The response says whether it was approved automatically (`auto_approved`) or is waiting for approval (`pending_approval`). The request stays pending until the matching `shift_claimed` arrives.
2. **`shift_claimed`**: a clinician claims the shift. Stafflion adds it to its schedule. For a shift Stafflion did not publish, the claim creates the shift, so the event must include `shift_start_time` and `shift_end_time`.
3. **`shift_update`**: the time of a taken shift changes. Send it only after the `shift_claimed` for that shift.
4. **`shift_call_out`**: a clinician calls out or will no longer work the shift. Stafflion removes the clinician from its schedule.

## Identifiers

* `partner_shift_id` identifies the shift in your system. Send it with every event.
* `shift_id` is the Stafflion shift ID. Send it only if you map it.
* `partner_secondary_shift_id` is a second identifier for the same shift in your system, when you use one.
* The clinician is identified in two ways, depending on the event. `shift_request` and `shift_claimed` send `partner_clinician` with `id` and the clinician's details. `shift_update` and `shift_call_out` send `partner_clinician_id`.
* Stafflion maps your identifiers to its own records.

## Times

`shift_start_time`, `shift_end_time`, and `occurred_at` are RFC 3339 timestamps. Send `Z` or an offset such as `+00:00`. Stafflion stores them in UTC and returns them in UTC.

`shift_end_time` must be after `shift_start_time`. If it is not, the event is rejected with 422.

## Pay details

`compensation` is optional. When you send it, it belongs to one shift and one clinician, and the amounts are in USD. Stafflion stores it for that assignment only: an event for another shift does not change it, and a later `shift_request` or `shift_claimed` for the same shift and clinician replaces it.

* `base_hourly_rate` and `overtime_hourly_rate` are required when `compensation` is sent.
* `bonus` is optional. Omit it when there is no bonus.
* `bonus.type` is `fixed` (an amount in USD) or `percentage`. A percentage is in points: `10` means 10%.
* Stafflion stores the bonus as sent. It also computes the bonus amount from `base_hourly_rate` over the length of the shift.
* `clinician_tier` is a property of the clinician, not of the pay. Send it in `partner_clinician`.

Pay details are not returned by any endpoint.

## Repeated events

Sending the same event again is safe. A repeat is the same `event_name`, `partner_shift_id`, `partner_facility_id`, and clinician. Stafflion responds with the same result as the first time and does not create a second shift or a second pending request.

## Order and dependencies

Stafflion applies events as they arrive, and each event must fit the state of the shift. For example, a `shift_update` before its `shift_claimed`, or a `shift_call_out` for a shift no clinician holds, is rejected with a 4xx. Resend the event after the event it depends on is accepted.

`occurred_at` records when the event happened. Stafflion does not use it to order events.

## After a shift_call_out

What happens to the shift depends on how your agency is set up with Stafflion:

* If your agency supports reopening, the shift reopens under the facility's rules.
* If your agency does not support it and Stafflion closes the shift, Stafflion cancels the shift.
* If your agency closes the shift on its own, Stafflion takes no action.

## Retries

Retry a `5xx` response or a timeout with backoff. Do not retry a `4xx` response, with one exception: an event that arrives before the event it depends on is rejected with a 4xx, and you resend it after that event is accepted.

## Errors

Every error returns a `message` that states the reason and a `code` you can match in your code. Match on `code`; the `message` text can change.

### Notes on errors

* **`shift_not_found` (404) on `shift_claimed`:** the shift is not available to your agency. It was removed, it was taken by another agency, or it is unknown and the event has no shift times. A 404 is final: do not retry. Stafflion creates a shift it did not publish only when the event includes `shift_start_time` and `shift_end_time`.
* **`ambiguous_shift` (400):** more than one shift or slot matches. Send the clinician identifier so Stafflion can choose the shift: `partner_clinician.id` on `shift_request` and `shift_claimed`, or `partner_clinician_id` on `shift_update` and `shift_call_out`.
* **`shift_not_taken` (400):** a `shift_call_out` needs a shift that a clinician holds.
* **`shift_time_unknown` (422):** Stafflion cannot determine the time of the shift from the event. Send `shift_start_time` and `shift_end_time`.
* **`facility_not_found` (404):** the `partner_facility_id` is not linked to a Stafflion facility. Ask your Stafflion contact to link it.
* **`validation_failed` (422):** `errors` lists each invalid field. Fix the field and resend.