Crew
STCW crew certifications.
GET
/stcw/{vesselId}/certificationsList a vessel's STCW certifications
Supports `?cursor=` pagination. "Get one certification by ID" is not on the public surface — no such route exists internally (see `docs/api.md` "Known gaps").
Path parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| vesselId | path | string (uuid) | required | — |
Query parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| cursor | query | string | optional | Opaque 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. |
| limit | query | integer | optional | — |
Response
| Field | Type | Required | Description |
|---|---|---|---|
| data | array<object> | required | — |
| data[].id | string (uuid) | optional | — |
| data[].vesselId | string (uuid) | optional | — |
| data[].userId | string (uuid) | optional | — |
| data[].certType | string | optional | — |
| data[].certName | string | optional | — |
| data[].issuingAuthority | string | null | optional | — |
| data[].certNumber | string | null | optional | — |
| data[].issuedDate | string (date-time) | null | optional | — |
| data[].expiryDate | string (date-time) | null | optional | — |
| data[].status | string | optional | — |
| data[].notes | string | null | optional | — |
| data[].user | object | optional | — |
| data[].user.id | string (uuid) | optional | — |
| data[].user.firstName | string | null | optional | — |
| data[].user.lastName | string | null | optional | — |
| data[].user.email | string | null | optional | — |
| data[].user.phone | string | null | optional | — |
| data[].user.profilePhoto | string | null | optional | — |
| data[].document | object | null | optional | — |
| data[].document.id | string (uuid) | optional | — |
| data[].document.title | string | optional | — |
| data[].document.fileUrl | string | null | optional | — |
| data[].document.fileSize | integer | null | optional | — |
| data[].document.mimeType | string | null | optional | — |
| data[].stcwDetail | object | null | optional | — |
| data[].stcwDetail.id | string (uuid) | optional | — |
| data[].stcwDetail.stcwCode | string | null | optional | — |
| data[].stcwDetail.stcwRegulation | string | null | optional | — |
| data[].stcwDetail.flagState | string | null | optional | — |
| data[].stcwDetail.endorsementNumber | string | null | optional | — |
| data[].stcwDetail.endorsementExpiry | string (date-time) | null | optional | — |
| data[].stcwDetail.revalidationDate | string (date-time) | null | optional | — |
| data[].stcwDetail.limitations | string | null | optional | — |
| data[].createdAt | string (date-time) | optional | — |
| data[].updatedAt | string (date-time) | optional | — |
| pagination | object | optional | Canonical 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.cursor | string | null | optional | Opaque token for the next page, or `null` when `hasMore` is `false`. |
| pagination.limit | integer | required | — |
| pagination.hasMore | boolean | required | — |
| pagination.total | integer | required | Total row count matching the filter (not just this page). |
GET
/vessels/{id}/teamList a vessel's team
Returns the vessel's crew roster (owner + team members), plus `teamTier` (plan context — member count, pending invites, seat limit, allowed roles) and `planContext` (downgrade-lock accounting). Team members beyond the caller's plan's seat limit are annotated `isLocked: true`; roles outside the plan's role allowlist are annotated `isRoleLocked: true`. Not cursor-paginated — crew rosters are bounded lists, not growing logs (see `docs/api.md` "Known gaps").
Path parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
Response
| Field | Type | Required | Description |
|---|---|---|---|
| data | object | required | — |
| data.members | array<object> | optional | — |
| data.members[].id | string (uuid) | optional | — |
| data.members[].email | string | optional | — |
| data.members[].firstName | string | null | optional | — |
| data.members[].lastName | string | null | optional | — |
| data.members[].profilePhoto | string | null | optional | — |
| data.members[].vesselRole | string | optional | VesselRole enum value, e.g. owner, co_owner, captain, crew, guest. |
| data.members[].permissions | array<string> | optional | — |
| data.members[].addedAt | string (date-time) | null | optional | — |
| data.members[].isOwner | boolean | optional | — |
| data.members[].isLocked | boolean | optional | — |
| data.members[].lockReason | string | optional | — |
| data.members[].isRoleLocked | boolean | optional | — |
| data.members[].roleLockReason | string | optional | — |
| data.teamTier | object | optional | — |
| data.teamTier.tier | string | null | optional | — |
| data.teamTier.memberCount | integer | optional | — |
| data.teamTier.pendingInvites | integer | optional | — |
| data.teamTier.limit | integer | null | optional | — |
| data.teamTier.allowedRoles | array<string> | null | optional | — |
| data.planContext | object | optional | — |
| data.planContext.planLimit | integer | null | optional | — |
| data.planContext.totalMembers | integer | optional | — |
| data.planContext.overlimit | boolean | optional | — |
