Maintenance

Maintenance event history and scheduling.

POST/maintenance

Create a maintenance event

Requires `vesselId`, `scheduledDate`, `description`, and `eventType`. `scope` defaults to `equipment` and determines which FK is required: `equipment` requires `equipmentId`, `system` requires `vesselSystemId`, `vessel` requires neither. On ISM-onboarded vessels, `responsibleUserId` is also required. Supports the `Idempotency-Key` request header (see `IdempotencyKeyHeader` parameter) — a repeat POST with the same key and the same request body within 24h returns the original response unchanged with `Idempotent-Replayed: true`; the same key with a *different* body returns `409 CONFLICT`.

Header parameters
NameInTypeRequiredDescription
Idempotency-KeyheaderstringoptionalClient-generated unique token (e.g. a UUID) scoping this write to be safely retried. Replaying the same key with the same request body within 24h returns the original cached response unchanged (with `Idempotent-Replayed: true`); replaying with a different body returns `409 CONFLICT`. Opt-in — omit for normal (non-idempotent) behavior.
Request body
FieldTypeRequiredDescription
vesselIdstring (uuid)required
scopeenum(equipment | system | vessel)optional
equipmentIdstring (uuid)optionalRequired when scope=equipment.
vesselSystemIdstring (uuid)optionalRequired when scope=system.
eventTypeenum(routine | repair | inspection | upgrade | refit | warranty)required
scheduledDatestring (date-time)required
descriptionstringrequired
priorityenum(low | medium | high | critical)optional
serviceProviderIdstring (uuid)optional
performedBystringoptional
currencystringoptional
responsibleUserIdstring (uuid)optionalRequired on ISM-onboarded vessels.
laborHoursnumberoptional
laborCoststringoptionalSerialized as string to preserve Decimal precision.
notesstringoptional
partsUsedarray<object>optional
partsUsed[].inventoryItemIdstring (uuid)required
partsUsed[].quantitynumberrequired
workflowIdstring (uuid)optional
Response
FieldTypeRequiredDescription
dataobjectrequired
data.idstring (uuid)optional
data.vesselIdstring (uuid)optional
data.equipmentIdstring (uuid) | nulloptional
data.vesselSystemIdstring (uuid) | nulloptional
data.scopestringoptionalMaintenanceScope enum: equipment, system, or vessel.
data.eventTypestringoptionalMaintenanceType enum: routine, repair, inspection, upgrade, refit, warranty.
data.statusstringoptionalDerived workflow-bucket status (not a stored column) — computed from `workflowExecution.currentState`.
data.prioritystringoptionalMaintenancePriority enum: low, medium, high, critical.
data.scheduledDatestring (date-time) | nulloptional
data.completedDatestring (date-time) | nulloptional
data.descriptionstring | nulloptional
data.performedBystring | nulloptional
data.serviceProviderIdstring (uuid) | nulloptional
data.serviceProviderobject | nulloptional
data.serviceProvider.idstring (uuid)optional
data.serviceProvider.businessNamestringoptional
data.serviceProvider.phonestring | nulloptional
data.partsUsedarray<object>optional
data.partsUsed[].inventoryItemIdstring (uuid)optional
data.partsUsed[].quantitynumberoptional
data.laborHoursnumber | nulloptional
data.laborCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.partsCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.totalCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.currencystringoptional
data.hoursAtServiceinteger | nulloptional
data.beforePhotosarray<string>optional
data.afterPhotosarray<string>optional
data.invoiceAttachmentsarray<string>optional
data.notesstring | nulloptional
data.technicianSignaturestring | nulloptional
data.technicianNamestring | nulloptional
data.technicianSignedAtstring (date-time) | nulloptional
data.requestedByIdstring (uuid) | nulloptional
data.responsibleUserIdstring (uuid) | nulloptional
data.linkedPermitIdstring (uuid) | nulloptional
data.equipmentobject | nulloptional
data.equipment.idstring (uuid)optional
data.equipment.equipmentTypestringoptional
data.equipment.makestring | nulloptional
data.equipment.modelstring | nulloptional
data.createdAtstring (date-time)optional
data.updatedAtstring (date-time)optional
cURL — idempotent create
curl -sS -X POST "https://api.owlmar.com/v1/maintenance" \
-H "Authorization: Bearer $OWLMAR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"vesselId": "'"$VESSEL_ID"'",
"equipmentId": "'"$EQUIPMENT_ID"'",
"eventType": "routine",
"scheduledDate": "2026-09-01T09:00:00.000Z",
"description": "500-hour service — port main engine"
}'
GET/maintenance/{id}

Get a maintenance event

Returns the full maintenance event with vessel, linked permit summary, recurring-schedule state, and current workflow state/transitions.

Path parameters
NameInTypeRequiredDescription
idpathstring (uuid)required
Response
FieldTypeRequiredDescription
dataanyrequired
PATCH/maintenance/{id}

Update a maintenance event

Partial update. Supports the `Idempotency-Key` header on the same terms as create.

Path parameters
NameInTypeRequiredDescription
idpathstring (uuid)required
Header parameters
NameInTypeRequiredDescription
Idempotency-KeyheaderstringoptionalClient-generated unique token (e.g. a UUID) scoping this write to be safely retried. Replaying the same key with the same request body within 24h returns the original cached response unchanged (with `Idempotent-Replayed: true`); replaying with a different body returns `409 CONFLICT`. Opt-in — omit for normal (non-idempotent) behavior.
Request body
FieldTypeRequiredDescription
eventTypeenum(routine | repair | inspection | upgrade | refit | warranty)optional
priorityenum(low | medium | high | critical)optional
scheduledDatestring (date-time) | nulloptional
completedDatestring (date-time) | nulloptional
descriptionstring | nulloptional
notesstring | nulloptional
laborHoursnumber | nulloptional
laborCoststring | nulloptionalSerialized as string to preserve Decimal precision.
partsUsedarray<object>optional
partsUsed[].inventoryItemIdstring (uuid)optional
partsUsed[].quantitynumberoptional
Response
FieldTypeRequiredDescription
dataobjectrequired
data.idstring (uuid)optional
data.vesselIdstring (uuid)optional
data.equipmentIdstring (uuid) | nulloptional
data.vesselSystemIdstring (uuid) | nulloptional
data.scopestringoptionalMaintenanceScope enum: equipment, system, or vessel.
data.eventTypestringoptionalMaintenanceType enum: routine, repair, inspection, upgrade, refit, warranty.
data.statusstringoptionalDerived workflow-bucket status (not a stored column) — computed from `workflowExecution.currentState`.
data.prioritystringoptionalMaintenancePriority enum: low, medium, high, critical.
data.scheduledDatestring (date-time) | nulloptional
data.completedDatestring (date-time) | nulloptional
data.descriptionstring | nulloptional
data.performedBystring | nulloptional
data.serviceProviderIdstring (uuid) | nulloptional
data.serviceProviderobject | nulloptional
data.serviceProvider.idstring (uuid)optional
data.serviceProvider.businessNamestringoptional
data.serviceProvider.phonestring | nulloptional
data.partsUsedarray<object>optional
data.partsUsed[].inventoryItemIdstring (uuid)optional
data.partsUsed[].quantitynumberoptional
data.laborHoursnumber | nulloptional
data.laborCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.partsCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.totalCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.currencystringoptional
data.hoursAtServiceinteger | nulloptional
data.beforePhotosarray<string>optional
data.afterPhotosarray<string>optional
data.invoiceAttachmentsarray<string>optional
data.notesstring | nulloptional
data.technicianSignaturestring | nulloptional
data.technicianNamestring | nulloptional
data.technicianSignedAtstring (date-time) | nulloptional
data.requestedByIdstring (uuid) | nulloptional
data.responsibleUserIdstring (uuid) | nulloptional
data.linkedPermitIdstring (uuid) | nulloptional
data.equipmentobject | nulloptional
data.equipment.idstring (uuid)optional
data.equipment.equipmentTypestringoptional
data.equipment.makestring | nulloptional
data.equipment.modelstring | nulloptional
data.createdAtstring (date-time)optional
data.updatedAtstring (date-time)optional
POST/maintenance/{id}/complete

Mark a maintenance event complete

Stamps `completedDate: now()`, optionally deducts `partsUsed` from inventory (if not already deducted), and accepts the same body fields as a PATCH for any final details captured at completion time (labor hours, cost, notes, technician signature, etc.).

Path parameters
NameInTypeRequiredDescription
idpathstring (uuid)required
Header parameters
NameInTypeRequiredDescription
Idempotency-KeyheaderstringoptionalClient-generated unique token (e.g. a UUID) scoping this write to be safely retried. Replaying the same key with the same request body within 24h returns the original cached response unchanged (with `Idempotent-Replayed: true`); replaying with a different body returns `409 CONFLICT`. Opt-in — omit for normal (non-idempotent) behavior.
Request body
FieldTypeRequiredDescription
partsUsedarray<object>optional
partsUsed[].inventoryItemIdstring (uuid)required
partsUsed[].quantitynumberrequired
laborHoursnumber | nulloptional
laborCoststring | nulloptionalSerialized as string to preserve Decimal precision.
notesstring | nulloptional
technicianSignaturestring | nulloptional
technicianNamestring | nulloptional
Response
FieldTypeRequiredDescription
dataobjectrequired
data.idstring (uuid)optional
data.vesselIdstring (uuid)optional
data.equipmentIdstring (uuid) | nulloptional
data.vesselSystemIdstring (uuid) | nulloptional
data.scopestringoptionalMaintenanceScope enum: equipment, system, or vessel.
data.eventTypestringoptionalMaintenanceType enum: routine, repair, inspection, upgrade, refit, warranty.
data.statusstringoptionalDerived workflow-bucket status (not a stored column) — computed from `workflowExecution.currentState`.
data.prioritystringoptionalMaintenancePriority enum: low, medium, high, critical.
data.scheduledDatestring (date-time) | nulloptional
data.completedDatestring (date-time) | nulloptional
data.descriptionstring | nulloptional
data.performedBystring | nulloptional
data.serviceProviderIdstring (uuid) | nulloptional
data.serviceProviderobject | nulloptional
data.serviceProvider.idstring (uuid)optional
data.serviceProvider.businessNamestringoptional
data.serviceProvider.phonestring | nulloptional
data.partsUsedarray<object>optional
data.partsUsed[].inventoryItemIdstring (uuid)optional
data.partsUsed[].quantitynumberoptional
data.laborHoursnumber | nulloptional
data.laborCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.partsCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.totalCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data.currencystringoptional
data.hoursAtServiceinteger | nulloptional
data.beforePhotosarray<string>optional
data.afterPhotosarray<string>optional
data.invoiceAttachmentsarray<string>optional
data.notesstring | nulloptional
data.technicianSignaturestring | nulloptional
data.technicianNamestring | nulloptional
data.technicianSignedAtstring (date-time) | nulloptional
data.requestedByIdstring (uuid) | nulloptional
data.responsibleUserIdstring (uuid) | nulloptional
data.linkedPermitIdstring (uuid) | nulloptional
data.equipmentobject | nulloptional
data.equipment.idstring (uuid)optional
data.equipment.equipmentTypestringoptional
data.equipment.makestring | nulloptional
data.equipment.modelstring | nulloptional
data.createdAtstring (date-time)optional
data.updatedAtstring (date-time)optional
GET/maintenance/vessel/{vesselId}

List a vessel's maintenance events

Returns maintenance events for a vessel with derived `status`, linked equipment, service provider, permit, schedule, and workflow-state info. Supports `?cursor=` pagination on the default (status-priority) sort path only — the `status=hours_due` filter branch (JS-side post-filter, no materialized sort column) does not support cursor and silently falls back to `?page=` semantics if combined with `?cursor=`.

Path parameters
NameInTypeRequiredDescription
vesselIdpathstring (uuid)required
Query parameters
NameInTypeRequiredDescription
cursorquerystringoptionalOpaque pagination cursor from a previous response's `pagination.cursor`. Omit this param entirely for the first page of cursor mode; pass `cursor=` (empty) is also accepted as "start from the beginning in cursor mode." Omitting `cursor` altogether (not even as an empty string) falls back to legacy `?page=` semantics on endpoints that still support it.
limitqueryintegeroptional
Response
FieldTypeRequiredDescription
dataarray<object>required
data[].idstring (uuid)optional
data[].vesselIdstring (uuid)optional
data[].equipmentIdstring (uuid) | nulloptional
data[].vesselSystemIdstring (uuid) | nulloptional
data[].scopestringoptionalMaintenanceScope enum: equipment, system, or vessel.
data[].eventTypestringoptionalMaintenanceType enum: routine, repair, inspection, upgrade, refit, warranty.
data[].statusstringoptionalDerived workflow-bucket status (not a stored column) — computed from `workflowExecution.currentState`.
data[].prioritystringoptionalMaintenancePriority enum: low, medium, high, critical.
data[].scheduledDatestring (date-time) | nulloptional
data[].completedDatestring (date-time) | nulloptional
data[].descriptionstring | nulloptional
data[].performedBystring | nulloptional
data[].serviceProviderIdstring (uuid) | nulloptional
data[].serviceProviderobject | nulloptional
data[].serviceProvider.idstring (uuid)optional
data[].serviceProvider.businessNamestringoptional
data[].serviceProvider.phonestring | nulloptional
data[].partsUsedarray<object>optional
data[].partsUsed[].inventoryItemIdstring (uuid)optional
data[].partsUsed[].quantitynumberoptional
data[].laborHoursnumber | nulloptional
data[].laborCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data[].partsCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data[].totalCoststring | nulloptionalSerialized as string to preserve Decimal precision.
data[].currencystringoptional
data[].hoursAtServiceinteger | nulloptional
data[].beforePhotosarray<string>optional
data[].afterPhotosarray<string>optional
data[].invoiceAttachmentsarray<string>optional
data[].notesstring | nulloptional
data[].technicianSignaturestring | nulloptional
data[].technicianNamestring | nulloptional
data[].technicianSignedAtstring (date-time) | nulloptional
data[].requestedByIdstring (uuid) | nulloptional
data[].responsibleUserIdstring (uuid) | nulloptional
data[].linkedPermitIdstring (uuid) | nulloptional
data[].equipmentobject | nulloptional
data[].equipment.idstring (uuid)optional
data[].equipment.equipmentTypestringoptional
data[].equipment.makestring | nulloptional
data[].equipment.modelstring | nulloptional
data[].createdAtstring (date-time)optional
data[].updatedAtstring (date-time)optional
paginationobjectoptionalCanonical cursor-pagination block. On endpoints not yet retrofitted for true cursor support, `cursor` is a best-effort display-only value (not decodable, no `?cursor=` branch accepts it back) — see each endpoint's description for whether it has full cursor support.
pagination.cursorstring | nulloptionalOpaque token for the next page, or `null` when `hasMore` is `false`.
pagination.limitintegerrequired
pagination.hasMorebooleanrequired
pagination.totalintegerrequiredTotal row count matching the filter (not just this page).