Expenses
Vessel operating expenses.
POST
/expensesCreate an expense
Requires `vesselId`, `date` (not in the future), and `amount`. `fundingSource: apa` requires `charterBookingId`.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| vesselId | string (uuid) | required | — |
| category | enum(fuel | maintenance | insurance | dockage | registration | crew | provisions | equipment | upgrades | cleaning | electronics | safety | navigation | communication | entertainment | crew_gratuity | crew_food | commission | delivery | marketing | food | beverages | excursions | permits | laundry | watersports | other) | optional | — |
| description | string | optional | — |
| amount | string | required | Serialized as string to preserve Decimal precision. |
| currency | string | optional | — |
| date | string (date) | required | Must not be in the future. |
| vendor | string | optional | — |
| charterBookingId | string (uuid) | optional | — |
| fundingSource | enum(owner | charter | apa) | optional | `apa` requires `charterBookingId`. |
| notes | string | optional | — |
| tags | array<string> | optional | — |
Response
| Field | Type | Required | Description |
|---|---|---|---|
| data | object | required | — |
| data.id | string (uuid) | optional | — |
| data.vesselId | string (uuid) | null | optional | — |
| data.category | string | optional | ExpenseCategory enum, e.g. fuel, maintenance, insurance, dockage, provisions, crew. |
| data.subcategory | string | null | optional | — |
| data.description | string | optional | — |
| data.amount | string | optional | Serialized as string to preserve Decimal precision. |
| data.currency | string | optional | — |
| data.date | string (date) | optional | — |
| data.vendor | string | null | optional | — |
| data.receiptUrl | string | null | optional | — |
| data.maintenanceId | string (uuid) | null | optional | — |
| data.equipmentId | string (uuid) | null | optional | — |
| data.notes | string | null | optional | — |
| data.tags | array<string> | optional | — |
| data.recurring | boolean | optional | — |
| data.recurringPeriod | string | null | optional | — |
| data.charterBookingId | string (uuid) | null | optional | — |
| data.charterBooking | object | null | optional | — |
| data.charterBooking.id | string (uuid) | optional | — |
| data.charterBooking.bookingReference | string | optional | — |
| data.fundingSource | enum(owner | charter | apa) | optional | — |
| data.costCenter | string | null | optional | — |
| data.quantity | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.unit | string | null | optional | — |
| data.quantityUsed | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.estimatedCost | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.provisionStatus | string | null | optional | — |
| data.tip | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.hasLineItems | boolean | optional | — |
| data.lineItemCount | integer | optional | — |
| data.reimbursementStatus | string | null | optional | — |
| data.isArchived | boolean | optional | — |
| data.createdAt | string (date-time) | optional | — |
| data.updatedAt | string (date-time) | optional | — |
GET
/expenses/{id}Get an expense
Returns a single expense. Pass `?include=lineItems,taxes` to inline OCR-extracted line items and taxes.
Path parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
Query parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| include | query | string | optional | Comma-separated related collections to inline — supports `lineItems`, `taxes`. |
Response
| Field | Type | Required | Description |
|---|---|---|---|
| data | any | required | — |
PATCH
/expenses/{id}Update an expense
Partial update — any writable `Expense` field.
Path parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string (uuid) | required | — |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| category | string | optional | — |
| description | string | optional | — |
| amount | string | optional | Serialized as string to preserve Decimal precision. |
| currency | string | optional | — |
| date | string (date) | optional | — |
| vendor | string | null | optional | — |
| notes | string | null | optional | — |
Response
| Field | Type | Required | Description |
|---|---|---|---|
| data | object | required | — |
| data.id | string (uuid) | optional | — |
| data.vesselId | string (uuid) | null | optional | — |
| data.category | string | optional | ExpenseCategory enum, e.g. fuel, maintenance, insurance, dockage, provisions, crew. |
| data.subcategory | string | null | optional | — |
| data.description | string | optional | — |
| data.amount | string | optional | Serialized as string to preserve Decimal precision. |
| data.currency | string | optional | — |
| data.date | string (date) | optional | — |
| data.vendor | string | null | optional | — |
| data.receiptUrl | string | null | optional | — |
| data.maintenanceId | string (uuid) | null | optional | — |
| data.equipmentId | string (uuid) | null | optional | — |
| data.notes | string | null | optional | — |
| data.tags | array<string> | optional | — |
| data.recurring | boolean | optional | — |
| data.recurringPeriod | string | null | optional | — |
| data.charterBookingId | string (uuid) | null | optional | — |
| data.charterBooking | object | null | optional | — |
| data.charterBooking.id | string (uuid) | optional | — |
| data.charterBooking.bookingReference | string | optional | — |
| data.fundingSource | enum(owner | charter | apa) | optional | — |
| data.costCenter | string | null | optional | — |
| data.quantity | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.unit | string | null | optional | — |
| data.quantityUsed | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.estimatedCost | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.provisionStatus | string | null | optional | — |
| data.tip | string | null | optional | Serialized as string to preserve Decimal precision. |
| data.hasLineItems | boolean | optional | — |
| data.lineItemCount | integer | optional | — |
| data.reimbursementStatus | string | null | optional | — |
| data.isArchived | boolean | optional | — |
| data.createdAt | string (date-time) | optional | — |
| data.updatedAt | string (date-time) | optional | — |
GET
/expenses/vessel/{vesselId}List a vessel's expenses
Supports `?cursor=` pagination on the non-search path only — `?search=` runs a bounded hybrid vector+ILIKE query and does not support cursor. The aggregate `totalAmount` (USD-normalized) is returned via `meta.totalAmount`, not as a top-level field.
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) | null | optional | — |
| data[].category | string | optional | ExpenseCategory enum, e.g. fuel, maintenance, insurance, dockage, provisions, crew. |
| data[].subcategory | string | null | optional | — |
| data[].description | string | optional | — |
| data[].amount | string | optional | Serialized as string to preserve Decimal precision. |
| data[].currency | string | optional | — |
| data[].date | string (date) | optional | — |
| data[].vendor | string | null | optional | — |
| data[].receiptUrl | string | null | optional | — |
| data[].maintenanceId | string (uuid) | null | optional | — |
| data[].equipmentId | string (uuid) | null | optional | — |
| data[].notes | string | null | optional | — |
| data[].tags | array<string> | optional | — |
| data[].recurring | boolean | optional | — |
| data[].recurringPeriod | string | null | optional | — |
| data[].charterBookingId | string (uuid) | null | optional | — |
| data[].charterBooking | object | null | optional | — |
| data[].charterBooking.id | string (uuid) | optional | — |
| data[].charterBooking.bookingReference | string | optional | — |
| data[].fundingSource | enum(owner | charter | apa) | optional | — |
| data[].costCenter | string | null | optional | — |
| data[].quantity | string | null | optional | Serialized as string to preserve Decimal precision. |
| data[].unit | string | null | optional | — |
| data[].quantityUsed | string | null | optional | Serialized as string to preserve Decimal precision. |
| data[].estimatedCost | string | null | optional | Serialized as string to preserve Decimal precision. |
| data[].provisionStatus | string | null | optional | — |
| data[].tip | string | null | optional | Serialized as string to preserve Decimal precision. |
| data[].hasLineItems | boolean | optional | — |
| data[].lineItemCount | integer | optional | — |
| data[].reimbursementStatus | string | null | optional | — |
| data[].isArchived | boolean | 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). |
| meta | object | optional | Endpoint-specific extra fields promoted out of the top level by envelope normalization (e.g. `totalAmount`, `planContext`, `hasApproximations`). |
