---
title: "Record a cycler's open service as done"
method: POST
path: "/cyclers/{cycler_id}/service_events/complete"
tags: ["Cyclers"]
---

# Record a cycler's open service as done

`POST /cyclers/{cycler_id}/service_events/complete`

Record service as done on a cycler.

Two paths behind one endpoint, chosen by whether the cycler is currently out
of service:

- **Open event** (it was taken out first): that event is completed and every
  channel incident pointing at it is closed in one write, so the cycler
  cannot end up half returned to service.
- **No open event**: the common case of "I calibrated this, log it". A
  single already-completed event is recorded from the request's
  ``event_type``. Nothing was taken out, so nothing needs returning, and no
  one has to open an event purely so it can be closed.

Either way a ``calibration`` advances ``last_calibrated_at`` — the only
supported way that field moves — and optionally updates
``calibration_interval_days``.

Addressed by cycler rather than by event id because a cycler has at most one
open event: the caller already knows which cycler it serviced, and looking
up the event id first would be a round-trip that proves nothing.

## Path parameters

- `cycler_id` string, required

## Request body

- object

## Response `200`

Successful Response

- CyclerServiceEvent — One instrument-level service on a cycler. A service event is the thing a channel incident belongs to when the whole cycler is down. Calibration is performed on the *instrument*, so a 40-channel cycler going in for its annual calibration is one event, not 40 unrelated outages that happen to share a category. Channel incidents opened for the event carry its id in ``service_event_id``, which is what lets one action close them together. At most one event per cycler may be open (``performed_at`` null) — a unique partial index enforces it, so "the current service" is a single unambiguous row and the open-event write path is safe to retry.
  - `id` string, required — Unique identifier for the service event
  - `organization_id` string, required — Organization this service event belongs to.
  - `project_id` string, required — Project that owns the cycler (pinned to it by FK)
  - `cycler_id` string, required — The cycler being serviced
  - `event_type` 'calibration' | 'preventive_maintenance' | 'firmware' | 'repair' | 'other', required — What kind of work took (or will take) a cycler out of service. Mirrors the ``cycler_service_events_shape_check`` CHECK constraint. Stored as CHECK-constrained text rather than a Postgres enum so the allowed set can be widened by swapping a constraint — ``ALTER TYPE ... ADD VALUE`` does not compose with the additive-migration rule. ``calibration`` is the one that feeds ``cyclers.last_calibrated_at``: completing an event of this type is what advances the calibration clock.
  - `scheduled_for` string, date-time, nullable — When the visit is booked. Required while the event is open; null is allowed on an event recorded after the fact.
  - `scheduled_until` string, date-time, nullable — When the booked visit is expected to end, making the booking a span rather than a start instant. Null on rows predating the column and on events recorded after the fact. A plan, not a constraint: a visit may legitimately run past it.
  - `performed_at` string, date-time, nullable — When the service was actually done. Null means the event is still open — at most one such event per cycler.
  - `notes` string, nullable — Free-text detail about the service
  - `created_by` string, nullable — User who opened or recorded the event
  - `performed_by` string, nullable — User who recorded the service as done
  - `created_at` string, date-time, required — Timestamp when the event row was created
  - `updated_at` string, date-time, required — Timestamp when the event row was last updated

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/ionworks/apis/fastapi.md) · [All operations](https://skmtc.dev/ionworks/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/ionworks/fastapi/revisions/7337a3cbdaf2/schema)
