# Freight API — Mutating Endpoints (Audit Surface) Every state-changing route in `apps/edr-freight-api` — `POST`, `PUT`, `PATCH`, `DELETE`. This is the candidate surface for audit logging: each row is an action a user can take that changes persisted state and therefore needs a who / what / when trail. All paths include the global prefix `api` (`app.setGlobalPrefix("api")` in `src/main.ts`). Titles come from each route's `@ApiOperation({ summary })`; where a route has none, the title is derived from its handler name. > Generated by reading the `@Post` / `@Put` / `@Patch` / `@Delete` decorators in > `src/**/*.controller.ts`. Re-generate after adding routes so this stays complete. ## Summary | Method | Count | | --- | ---: | | `POST` | 351 | | `PUT` | 8 | | `PATCH` | 72 | | `DELETE` | 61 | | **Total** | **492** | Across **66** entities. ## Entity index | Entity | Endpoints | | --- | ---: | | [Account](#account) | 3 | | [AI Assist](#ai-assist) | 1 | | [Approval Rule](#approval-rule) | 5 | | [Booking](#booking) | 57 | | [Cargo](#cargo) | 6 | | [Cargo Type](#cargo-type) | 5 | | [Company](#company) | 30 | | [Compliance](#compliance) | 3 | | [Consignment](#consignment) | 1 | | [Container](#container) | 5 | | [Container Type](#container-type) | 5 | | [Contract](#contract) | 68 | | [Contract Template](#contract-template) | 8 | | [Driver](#driver) | 5 | | [Dropdown Setting](#dropdown-setting) | 7 | | [EIMS Invoice](#eims-invoice) | 3 | | [Exchange Setting](#exchange-setting) | 1 | | [Facility](#facility) | 3 | | [Fayda Verification](#fayda-verification) | 1 | | [File Upload Setting](#file-upload-setting) | 7 | | [First Mile](#first-mile) | 7 | | [Fuel](#fuel) | 1 | | [GPS Tracking](#gps-tracking) | 3 | | [Import Operation](#import-operation) | 9 | | [Incident](#incident) | 3 | | [Interchange Document](#interchange-document) | 3 | | [Last Mile](#last-mile) | 10 | | [Last Mile Request](#last-mile-request) | 4 | | [Locomotive](#locomotive) | 4 | | [Maintenance](#maintenance) | 13 | | [Notification Inbox](#notification-inbox) | 2 | | [Organization User](#organization-user) | 2 | | [OTP](#otp) | 2 | | [Password Reset](#password-reset) | 4 | | [Payment](#payment) | 7 | | [Priority Config](#priority-config) | 5 | | [Priority Rule Change Request](#priority-rule-change-request) | 3 | | [Procurement](#procurement) | 8 | | [Rate](#rate) | 5 | | [Rate Change Request](#rate-change-request) | 3 | | [Route](#route) | 4 | | [Schedule](#schedule) | 3 | | [Service Type](#service-type) | 5 | | [Shipping Line](#shipping-line) | 3 | | [Signature](#signature) | 1 | | [Support Chat](#support-chat) | 5 | | [Support Content](#support-content) | 3 | | [Train](#train) | 3 | | [Train Build](#train-build) | 11 | | [Train Schedule](#train-schedule) | 48 | | [Transit Agent](#transit-agent) | 3 | | [Truck Type](#truck-type) | 3 | | [User Trade Access](#user-trade-access) | 1 | | [Vehicle](#vehicle) | 3 | | [Wagon](#wagon) | 8 | | [Wagon Transfer Request](#wagon-transfer-request) | 5 | | [Wagon Type](#wagon-type) | 3 | | [Warehouse](#warehouse) | 12 | | [Warehouse Fee Invoice](#warehouse-fee-invoice) | 5 | | [Warehouse Inspection Report](#warehouse-inspection-report) | 3 | | [Warehouse Inventory](#warehouse-inventory) | 24 | | [Warehouse Yard](#warehouse-yard) | 2 | | [Warehouse Zone](#warehouse-zone) | 1 | | [Weight Limit Rule](#weight-limit-rule) | 3 | | [Yard](#yard) | 5 | | [Yard Distance](#yard-distance) | 3 | --- ## Endpoints by entity ### Account | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Send a verification code to a new email/phone before changing it | `POST` | `/api/me/contact/otp` | `modules/auth/account.controller.ts:26` | | Change the account's email or phone, gated by a verification code | `PATCH` | `/api/me/contact` | `modules/auth/account.controller.ts:40` | | Change the account's display name | `PATCH` | `/api/me/name` | `modules/auth/account.controller.ts:54` | ### AI Assist | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Mock AI: extract structured booking fields from free-text request | `POST` | `/api/ai/booking/extract` | `modules/ai/ai.controller.ts:16` | ### Approval Rule | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create an approval rule step | `POST` | `/api/approval-rules` | `modules/rule-engine/controllers/approval-rules.controller.ts:66` | | Move an approval step up or down within its chain | `POST` | `/api/approval-rules/:id/move-order` | `modules/rule-engine/controllers/approval-rules.controller.ts:51` | | Bulk reorder approval steps within a chain | `POST` | `/api/approval-rules/reorder` | `modules/rule-engine/controllers/approval-rules.controller.ts:43` | | Update an approval rule | `PATCH` | `/api/approval-rules/:id` | `modules/rule-engine/controllers/approval-rules.controller.ts:73` | | Soft-delete an approval rule | `DELETE` | `/api/approval-rules/:id` | `modules/rule-engine/controllers/approval-rules.controller.ts:80` | ### Booking | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new freight booking (DRAFT) | `POST` | `/api/bookings` | `modules/bookings/bookings.controller.ts:170` | | Allocate containers to vehicles | `POST` | `/api/bookings/:bookingId/allocate-containers` | `modules/bookings/booking-allocation.controller.ts:13` | | Cancel booking | `POST` | `/api/bookings/:id/cancel` | `modules/bookings/bookings.controller.ts:1544` | | Customer cancels an unpaid hold (SELECTED_FOR_BATCH → CANCELLED); | `POST` | `/api/bookings/:id/cancel-hold` | `modules/bookings/bookings.controller.ts:1568` | | GL ET uploads customs declaration on booking (GENERAL customs) | `POST` | `/api/bookings/:id/clearance/declaration` | `modules/bookings/bookings.controller.ts:1126` | | Upload Booking Delivery Order | `POST` | `/api/bookings/:id/clearance/delivery-order` | `modules/bookings/bookings.controller.ts:1268` | | Customer uploads clearance documents (fieldname = document key) | `POST` | `/api/bookings/:id/clearance/documents` | `modules/bookings/bookings.controller.ts:959` | | GL ET sends a draft customs declaration (multi-file) with an estimated price for the customer to review | `POST` | `/api/bookings/:id/clearance/draft-declaration` | `modules/bookings/bookings.controller.ts:1175` | | Customer accepts the draft customs declaration — unlocks the real customs declaration step for GL Ethiopia | `POST` | `/api/bookings/:id/clearance/draft-declaration/accept` | `modules/bookings/bookings.controller.ts:1200` | | Customer requests a change to the draft customs declaration with a reason — GL Ethiopia sends a corrected draft (repeatable) | `POST` | `/api/bookings/:id/clearance/draft-declaration/change` | `modules/bookings/bookings.controller.ts:1211` | | GL ET sets duty/tax on booking with notice attachment | `POST` | `/api/bookings/:id/clearance/duty` | `modules/bookings/bookings.controller.ts:1144` | | Customer uploads duty/tax payment slip on booking | `POST` | `/api/bookings/:id/clearance/duty-slip` | `modules/bookings/bookings.controller.ts:1238` | | Confirm Booking Export Release | `POST` | `/api/bookings/:id/clearance/export-release` | `modules/bookings/bookings.controller.ts:1326` | | GL finalizes clearance (requires 100% approved) → CLEARANCE_READY | `POST` | `/api/bookings/:id/clearance/finalize` | `modules/bookings/bookings.controller.ts:1087` | | GL ET finalizes import pre-clearance on booking | `POST` | `/api/bookings/:id/clearance/finalize-pre-clearance` | `modules/bookings/bookings.controller.ts:1230` | | GL uploads customs output documents (IM4/EX3/…) | `POST` | `/api/bookings/:id/clearance/output-documents` | `modules/bookings/bookings.controller.ts:1071` | | Customer requests operation with a schedule day | `POST` | `/api/bookings/:id/clearance/proceed` | `modules/bookings/bookings.controller.ts:979` | | Upload Booking Release Order | `POST` | `/api/bookings/:id/clearance/release-order` | `modules/bookings/bookings.controller.ts:1288` | | GL reviews a clearance document (Approve | Query) | `POST` | `/api/bookings/:id/clearance/review` | `modules/bookings/bookings.controller.ts:1051` | | Request Booking RO Amendment | `POST` | `/api/bookings/:id/clearance/ro-amendment` | `modules/bookings/bookings.controller.ts:1311` | | GL Djibouti picks the transit officer from the roster — unblocks the customs declaration; calling again reassigns | `POST` | `/api/bookings/:id/clearance/transit-assignee/assign` | `modules/bookings/bookings.controller.ts:1112` | | GL ET asks GL Djibouti to name the transit officer — required before the import customs declaration | `POST` | `/api/bookings/:id/clearance/transit-assignee/request` | `modules/bookings/bookings.controller.ts:1098` | | Upload Booking Transit Permit | `POST` | `/api/bookings/:id/clearance/transit-permit` | `modules/bookings/bookings.controller.ts:1251` | | Confirm submit after price change | `POST` | `/api/bookings/:id/confirm-submit` | `modules/bookings/bookings.controller.ts:906` | | Request freight consolidation | `POST` | `/api/bookings/:id/consolidation` | `modules/bookings/bookings.controller.ts:1583` | | Generate contract PDF from template | `POST` | `/api/bookings/:id/contract/generate` | `modules/bookings/bookings.controller.ts:1406` | | Apply digital signature (customer or staff) | `POST` | `/api/bookings/:id/contract/sign` | `modules/bookings/bookings.controller.ts:1452` | | Customer cancels their own booking before payment — no cancellation fee | `POST` | `/api/bookings/:id/customer-cancel` | `modules/bookings/bookings.controller.ts:1555` | | Customer assigns external truck and driver for terminal pickup | `POST` | `/api/bookings/:id/customer-truck-assignment` | `modules/bookings/bookings.controller.ts:460` | | Add a customer self-haul truck carrying 1–2 of the booking containers | `POST` | `/api/bookings/:id/customer-trucks` | `modules/bookings/bookings.controller.ts:686` | | Register an import truck leaving: containers loaded + weighed gross (staff) | `POST` | `/api/bookings/:id/customer-trucks/:assignmentId/depart` | `modules/bookings/bookings.controller.ts:788` | | Truck_dispatch: load selected containers onto a truck (staff) | `POST` | `/api/bookings/:id/customer-trucks/:assignmentId/load` | `modules/bookings/bookings.controller.ts:773` | | Bulk add customer trucks from array payload (Excel parsed) | `POST` | `/api/bookings/:id/customer-trucks/bulk` | `modules/bookings/bookings.controller.ts:701` | | Customer digital signature (deprecated — use POST contract/sign) | `POST` | `/api/bookings/:id/customer/sign` | `modules/bookings/bookings.controller.ts:1487` | | Upload documents for a booking (DRAFT only) | `POST` | `/api/bookings/:id/documents` | `modules/bookings/bookings.controller.ts:869` | | Generate a GRN over the received containers (all received, or a subset) — one GRN per batch | `POST` | `/api/bookings/:id/generate-grn` | `modules/bookings/bookings.controller.ts:820` | | Generate price preview (DRAFT or CHANGES_REQUESTED) | `POST` | `/api/bookings/:id/generate-price` | `modules/bookings/bookings.controller.ts:882` | | Expedite government booking to PAID / ELIGIBLE for scheduling | `POST` | `/api/bookings/:id/government-expedite` | `modules/bookings/bookings.controller.ts:1390` | | Staff contract signature and fully execute (use contract/sign STAFF preferred) | `POST` | `/api/bookings/:id/marketing/approve` | `modules/bookings/bookings.controller.ts:1505` | | Operations reviews an operation request: ACCEPT (→ batch pool), | `POST` | `/api/bookings/:id/operation/review` | `modules/bookings/bookings.controller.ts:1030` | | Mark completed | `POST` | `/api/bookings/:id/operations/complete` | `modules/bookings/bookings.controller.ts:1536` | | Mark in transit | `POST` | `/api/bookings/:id/operations/start-transit` | `modules/bookings/bookings.controller.ts:1528` | | Customer reject price estimate | `POST` | `/api/bookings/:id/reject` | `modules/bookings/bookings.controller.ts:918` | | Staff accept intake → set contract validity window + start approval chain | `POST` | `/api/bookings/:id/staff/accept` | `modules/bookings/bookings.controller.ts:1355` | | Staff final reject | `POST` | `/api/bookings/:id/staff/reject` | `modules/bookings/bookings.controller.ts:1374` | | Staff return booking for customer updates | `POST` | `/api/bookings/:id/staff/request-changes` | `modules/bookings/bookings.controller.ts:1339` | | Customer submit booking | `POST` | `/api/bookings/:id/submit` | `modules/bookings/bookings.controller.ts:894` | | Request a partial wagon cancellation on a PAID booking — opens the cancellation-fee invoice; wagons are released only once the fee settles | `POST` | `/api/bookings/:id/wagon-cancellations` | `modules/bookings/bookings.controller.ts:558` | | Preview the fee/credit of a partial wagon cancellation (no writes) | `POST` | `/api/bookings/:id/wagon-cancellations/preview` | `modules/bookings/bookings.controller.ts:544` | | Rebook a wagon-cancellation credit: pick a shipment day only — the new booking is created under the contract and marked PAID (freight already paid; contract must still be valid) | `POST` | `/api/bookings/wagon-cancellations/:cancellationId/rebook` | `modules/bookings/bookings.controller.ts:638` | | Withdraw a fee-pending wagon cancellation (owner, or staff with the void permission) | `POST` | `/api/bookings/wagon-cancellations/:cancellationId/withdraw` | `modules/bookings/bookings.controller.ts:624` | | Update booking | `PATCH` | `/api/bookings/:id` | `modules/bookings/bookings.controller.ts:211` | | Edit a not-yet-arrived customer truck (plate/driver/type + containers) | `PATCH` | `/api/bookings/:id/customer-trucks/:assignmentId` | `modules/bookings/bookings.controller.ts:716` | | Export only: choose direct truck-to-train (no warehouse, no GRN) or warehouse first | `PATCH` | `/api/bookings/:id/export-handover-mode` | `modules/bookings/bookings.controller.ts:761` | | Soft-delete DRAFT booking | `DELETE` | `/api/bookings/:id` | `modules/bookings/bookings.controller.ts:861` | | Remove consolidation pairing | `DELETE` | `/api/bookings/:id/consolidation` | `modules/bookings/bookings.controller.ts:1590` | | Remove a not-yet-arrived customer truck from a booking | `DELETE` | `/api/bookings/:id/customer-trucks/:assignmentId` | `modules/bookings/bookings.controller.ts:732` | ### Cargo | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new cargo | `POST` | `/api/cargoes` | `modules/cargoes/cargoes.controller.ts:34` | | Mark cargo as delivered | `POST` | `/api/cargoes/:id/deliver` | `modules/cargoes/cargoes.controller.ts:81` | | Load cargo into a container | `POST` | `/api/cargoes/:id/load` | `modules/cargoes/cargoes.controller.ts:67` | | Unload cargo from container | `POST` | `/api/cargoes/:id/unload` | `modules/cargoes/cargoes.controller.ts:74` | | Update a cargo | `PATCH` | `/api/cargoes/:id` | `modules/cargoes/cargoes.controller.ts:53` | | Delete a cargo | `DELETE` | `/api/cargoes/:id` | `modules/cargoes/cargoes.controller.ts:60` | ### Cargo Type | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a cargo type | `POST` | `/api/cargo-types` | `modules/rule-engine/controllers/cargo-types.controller.ts:51` | | Move a cargo type up or down in display order | `POST` | `/api/cargo-types/:id/move-order` | `modules/rule-engine/controllers/cargo-types.controller.ts:36` | | Bulk reorder cargo types by ID list | `POST` | `/api/cargo-types/reorder` | `modules/rule-engine/controllers/cargo-types.controller.ts:28` | | Update a cargo type | `PATCH` | `/api/cargo-types/:id` | `modules/rule-engine/controllers/cargo-types.controller.ts:58` | | Soft-delete a cargo type | `DELETE` | `/api/cargo-types/:id` | `modules/rule-engine/controllers/cargo-types.controller.ts:65` | ### Company | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new company (customer, freight_forwarder, dj_freight_forwarder, transporter) | `POST` | `/api/companies` | `modules/companies/companies.controller.ts:565` | | Upload documents for a company (onboarding) | `POST` | `/api/companies/:companyId/documents` | `modules/companies/companies.controller.ts:728` | | Add a profile (employee) to a company | `POST` | `/api/companies/:companyId/profiles` | `modules/companies/companies.controller.ts:843` | | Approve a pending profile change request (applies the changes) | `POST` | `/api/companies/change-requests/:id/approve` | `modules/companies/companies.controller.ts:790` | | Reject a pending profile change request with a note | `POST` | `/api/companies/change-requests/:id/reject` | `modules/companies/companies.controller.ts:806` | | Ask for specific changes on a pending request without rejecting it (row stays open, next edit appends to it) | `POST` | `/api/companies/change-requests/:id/request-changes` | `modules/companies/companies.controller.ts:824` | | Create a single operational profile for the current user's company. The role starts pending and does not become the active mode | `POST` | `/api/companies/company-profile` | `modules/companies/companies.controller.ts:272` | | Add operational profile(s) (importer/exporter/forwarder) to the current user's company | `POST` | `/api/companies/company-profiles` | `modules/companies/companies.controller.ts:229` | | Add business-license document(s) to a profile. For an approved company | `POST` | `/api/companies/company-profiles/:profileId/license` | `modules/companies/companies.controller.ts:290` | | Replace a business-license file with a newly uploaded one (staged for | `POST` | `/api/companies/company-profiles/:profileId/license/:fileId/replace` | `modules/companies/companies.controller.ts:311` | | Resubmit a rejected operational role for approval (→ pending) | `POST` | `/api/companies/company-profiles/:profileId/reapply` | `modules/companies/companies.controller.ts:165` | | Create a company with its associated external profile (onboarding) | `POST` | `/api/companies/create` | `modules/companies/companies.controller.ts:539` | | Ask the customer to correct one uploaded document | `POST` | `/api/companies/documents/:fileId/request-change` | `modules/companies/companies.controller.ts:699` | | Fetch company info from eTrade by TIN | `POST` | `/api/companies/fetch-etrade-info` | `modules/companies/companies.controller.ts:197` | | Bind a completed Fayda verification to the company's owner or Power of Attorney | `POST` | `/api/companies/identity/fayda/complete` | `modules/companies/companies.controller.ts:414` | | Declare the General Manager is the company's owner, copying the owner's verified identity across | `POST` | `/api/companies/identity/gm/same-as-owner` | `modules/companies/companies.controller.ts:432` | | Declare the Power of Attorney is the company's owner, copying the owner's identity across | `POST` | `/api/companies/identity/poa/same-as-owner` | `modules/companies/companies.controller.ts:461` | | Mark the current user's onboarding as complete | `POST` | `/api/companies/onboarding/complete` | `modules/companies/companies.controller.ts:527` | | Begin onboarding: create a draft company + profile + role(s) so later steps can save incrementally | `POST` | `/api/companies/onboarding/start` | `modules/companies/companies.controller.ts:246` | | Upload the Power of Attorney delegation letter, replacing any existing one | `POST` | `/api/companies/poa-delegation` | `modules/companies/companies.controller.ts:380` | | Update a company | `PATCH` | `/api/companies/:id` | `modules/companies/companies.controller.ts:613` | | Update a company profile's approval status | `PATCH` | `/api/companies/company-profiles/:profileId/status` | `modules/companies/companies.controller.ts:748` | | Persist the user's current onboarding wizard step | `PATCH` | `/api/companies/onboarding-step` | `modules/companies/companies.controller.ts:504` | | Update profile (flattened settings page) | `PATCH` | `/api/companies/profile` | `modules/companies/companies.controller.ts:219` | | Soft-delete a company | `DELETE` | `/api/companies/:id` | `modules/companies/companies.controller.ts:634` | | Remove a business-license file (staged for review on an approved company) | `DELETE` | `/api/companies/company-profiles/:profileId/license/:fileId` | `modules/companies/companies.controller.ts:338` | | Remove the company's Power of Attorney — the verified identity, its details and the delegation paper together | `DELETE` | `/api/companies/identity/fayda/poa` | `modules/companies/companies.controller.ts:491` | | Clear the General Manager's identity — the \"same as owner\" declaration or a verification, and the details either wrote | `DELETE` | `/api/companies/identity/gm` | `modules/companies/companies.controller.ts:448` | | Undo the Power of Attorney \"same as owner\" declaration and the identity it copied, leaving the representative open to be verified in their own right | `DELETE` | `/api/companies/identity/poa/same-as-owner` | `modules/companies/companies.controller.ts:478` | | Remove the Power of Attorney delegation letter (staged for review on an approved company) | `DELETE` | `/api/companies/poa-delegation/:fileId` | `modules/companies/companies.controller.ts:401` | ### Compliance | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a compliance record | `POST` | `/api/compliance` | `modules/compliance/compliance.controller.ts:23` | | Update a compliance record | `PATCH` | `/api/compliance/:id` | `modules/compliance/compliance.controller.ts:51` | | Soft-delete a compliance record | `DELETE` | `/api/compliance/:id` | `modules/compliance/compliance.controller.ts:58` | ### Consignment | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new consignment | `POST` | `/api/consignments` | `modules/consignments/consignments.controller.ts:29` | ### Container | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new container | `POST` | `/api/containers` | `modules/container-management/containers.controller.ts:33` | | Assign container to a wagon | `POST` | `/api/containers/:id/assign-wagon` | `modules/container-management/containers.controller.ts:66` | | Unassign container from wagon | `POST` | `/api/containers/:id/unassign-wagon` | `modules/container-management/containers.controller.ts:73` | | Update a container | `PATCH` | `/api/containers/:id` | `modules/container-management/containers.controller.ts:52` | | Delete a container | `DELETE` | `/api/containers/:id` | `modules/container-management/containers.controller.ts:59` | ### Container Type | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a container type | `POST` | `/api/container-types` | `modules/rule-engine/controllers/container-types.controller.ts:51` | | Move a container type up or down in display order | `POST` | `/api/container-types/:id/move-order` | `modules/rule-engine/controllers/container-types.controller.ts:36` | | Bulk reorder container types by ID list | `POST` | `/api/container-types/reorder` | `modules/rule-engine/controllers/container-types.controller.ts:28` | | Update a container type | `PATCH` | `/api/container-types/:id` | `modules/rule-engine/controllers/container-types.controller.ts:58` | | Soft-delete a container type | `DELETE` | `/api/container-types/:id` | `modules/rule-engine/controllers/container-types.controller.ts:65` | ### Contract | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new contract (DRAFT) with routes + cargo scope | `POST` | `/api/contracts` | `modules/contracts/contracts.controller.ts:188` | | Approve one approval step in sequence | `POST` | `/api/contracts/:id/approval-steps/:stepId/approve` | `modules/contracts/contracts.controller.ts:552` | | Reject one approval step — to the customer (terminal → REJECTED) or, via returnToStepId, back to an earlier approver (chain re-runs from there) | `POST` | `/api/contracts/:id/approval-steps/:stepId/reject` | `modules/contracts/contracts.controller.ts:571` | | Customer submits a shipment request on a GENERAL customs contract | `POST` | `/api/contracts/:id/booking-requests` | `modules/contracts/contracts.controller.ts:170` | | Create a shipment booking under a contract — Path A (customer) or Path B (GL Ethiopia) | `POST` | `/api/contracts/:id/bookings` | `modules/contracts/contracts.controller.ts:1076` | | Complete an initiated booking after Operations finalized its clearance — cargo + binding day, window and departure checks, pricing and invoicing | `POST` | `/api/contracts/:id/bookings/:bookingId/complete` | `modules/contracts/contracts.controller.ts:1133` | | Initiate a bare booking instance under an import/export contract (ONE_TIME or GENERAL) — no cargo, no date; enters per-booking clearance (AWAITING_DOCUMENTS). ONE_TIME customs instances are opened by the customer (or GL); GENERAL customs comes from a shipment request | `POST` | `/api/contracts/:id/bookings/initiate` | `modules/contracts/contracts.controller.ts:1105` | | Customer cancels their own contract (blocked while a booking is live) | `POST` | `/api/contracts/:id/cancel` | `modules/contracts/contracts.controller.ts:526` | | GL ET uploads customs declaration documents (multi-file) | `POST` | `/api/contracts/:id/clearance/declaration` | `modules/contracts/contracts.controller.ts:795` | | GL DJ uploads Delivery Order (import) with vessel arrival + DO collected dates | `POST` | `/api/contracts/:id/clearance/delivery-order` | `modules/contracts/contracts.controller.ts:957` | | Customer uploads clearance documents (fieldname = document key) | `POST` | `/api/contracts/:id/clearance/documents` | `modules/contracts/contracts.controller.ts:734` | | GL replaces a clearance document in place (reason required) — the previous version is kept in the file history and the new one needs approving | `POST` | `/api/contracts/:id/clearance/documents/:fileKey/replace` | `modules/contracts/contracts.controller.ts:894` | | GL ET sets duty/tax requirement and advises amount with notice attachment | `POST` | `/api/contracts/:id/clearance/duty` | `modules/contracts/contracts.controller.ts:808` | | Customer uploads duty/tax payment slip on contract | `POST` | `/api/contracts/:id/clearance/duty-slip` | `modules/contracts/contracts.controller.ts:932` | | Customer disputes the advised duty/tax with a reason — reopens the step so GL Ethiopia can re-advise (repeatable) | `POST` | `/api/contracts/:id/clearance/duty/dispute` | `modules/contracts/contracts.controller.ts:918` | | GL ET confirms export release after declaration | `POST` | `/api/contracts/:id/clearance/export-release` | `modules/contracts/contracts.controller.ts:1008` | | GL ET finalizes clearance → CLEARANCE_READY_FOR_BOOKING (legacy) | `POST` | `/api/contracts/:id/clearance/finalize` | `modules/contracts/contracts.controller.ts:788` | | GL ET finalizes export clearance after post-booking transit permit upload | `POST` | `/api/contracts/:id/clearance/finalize-export-clearance` | `modules/contracts/contracts.controller.ts:1018` | | GL ET finalizes import pre-clearance — unlocks Djibouti DO upload | `POST` | `/api/contracts/:id/clearance/finalize-pre-clearance` | `modules/contracts/contracts.controller.ts:838` | | Operations finalizes self-clearance → customer may create the booking | `POST` | `/api/contracts/:id/clearance/ops-finalize` | `modules/contracts/contracts.controller.ts:1051` | | Operations reviews a customer self-clearance document (Approve | Query) | `POST` | `/api/contracts/:id/clearance/ops-review` | `modules/contracts/contracts.controller.ts:1032` | | GL uploads customs output documents (IM4/EX3/…) pre-booking | `POST` | `/api/contracts/:id/clearance/output-documents` | `modules/contracts/contracts.controller.ts:776` | | GL DJ uploads Release Order + vessel departure date (export) | `POST` | `/api/contracts/:id/clearance/release-order` | `modules/contracts/contracts.controller.ts:978` | | GL ET reviews a clearance document (Approve | Query) | `POST` | `/api/contracts/:id/clearance/review` | `modules/contracts/contracts.controller.ts:756` | | GL DJ requests port amendment when RO vessel window is too short | `POST` | `/api/contracts/:id/clearance/ro-amendment` | `modules/contracts/contracts.controller.ts:997` | | GL Djibouti picks the transit officer from the roster — unblocks the customs declaration; calling again reassigns | `POST` | `/api/contracts/:id/clearance/transit-assignee/assign` | `modules/contracts/contracts.controller.ts:863` | | GL ET asks GL Djibouti to name the transit officer — required before the customs declaration | `POST` | `/api/contracts/:id/clearance/transit-assignee/request` | `modules/contracts/contracts.controller.ts:845` | | GL ET uploads import transit permit documents (multi-file) | `POST` | `/api/contracts/:id/clearance/transit-permit` | `modules/contracts/contracts.controller.ts:944` | | Confirm submit after a price change | `POST` | `/api/contracts/:id/confirm-submit` | `modules/contracts/contracts.controller.ts:380` | | Generate contract document → CONTRACT_READY | `POST` | `/api/contracts/:id/contract/generate` | `modules/contracts/contracts.controller.ts:596` | | Send the sudo-mode signing OTP to the contract company's registered phone (server picks the number) | `POST` | `/api/contracts/:id/contract/send-signing-otp` | `modules/contracts/contracts.controller.ts:667` | | Apply digital signature (customer or staff/director/ceo) | `POST` | `/api/contracts/:id/contract/sign` | `modules/contracts/contracts.controller.ts:680` | | Upload intake documents for a contract (DRAFT only) | `POST` | `/api/contracts/:id/documents` | `modules/contracts/contracts.controller.ts:354` | | Generate unit-rate breakdown (no totals at contract phase) | `POST` | `/api/contracts/:id/generate-price` | `modules/contracts/contracts.controller.ts:366` | | GL marks a pre-booking (contract) milestone complete | `POST` | `/api/contracts/:id/milestones/:code/complete` | `modules/contracts/contracts.controller.ts:1222` | | Create a renewal draft linked via renewalOfId | `POST` | `/api/contracts/:id/renew` | `modules/contracts/contracts.controller.ts:705` | | Staff lift a suspension — contract returns to its prior status | `POST` | `/api/contracts/:id/resume` | `modules/contracts/contracts.controller.ts:510` | | Staff accept → set validity window + start approval chain | `POST` | `/api/contracts/:id/staff/accept` | `modules/contracts/contracts.controller.ts:387` | | Staff reject contract | `POST` | `/api/contracts/:id/staff/reject` | `modules/contracts/contracts.controller.ts:476` | | Staff return contract for customer updates | `POST` | `/api/contracts/:id/staff/request-changes` | `modules/contracts/contracts.controller.ts:460` | | Customer submit contract (freezes contract_rate_snapshots) | `POST` | `/api/contracts/:id/submit` | `modules/contracts/contracts.controller.ts:373` | | Staff freeze a signed contract (reversible, any post-signature step) | `POST` | `/api/contracts/:id/suspend` | `modules/contracts/contracts.controller.ts:492` | | Pre-create validation + authoritative price preview: full booking price breakdown (rail, first/last mile, surcharges), overweight lines and 20ft weight-pairing errors for a shipment payload (no booking created) | `POST` | `/api/contracts/:id/validate-shipment` | `modules/contracts/contracts.controller.ts:1162` | | GL marks a shipment request accepted + links the created booking | `POST` | `/api/contracts/booking-requests/:reqId/accept` | `modules/contracts/contracts.controller.ts:134` | | Customer cancels their own pending shipment request | `POST` | `/api/contracts/booking-requests/:reqId/cancel` | `modules/contracts/contracts.controller.ts:160` | | GL rejects a shipment request | `POST` | `/api/contracts/booking-requests/:reqId/reject` | `modules/contracts/contracts.controller.ts:149` | | GL uploads post-booking operational documents (DO/RO/T1/…) | `POST` | `/api/contracts/bookings/:bookingId/documents` | `modules/contracts/contracts.controller.ts:1441` | | GL ET advises duty & tax amount + declaration serial | `POST` | `/api/contracts/bookings/:bookingId/duty` | `modules/contracts/contracts.controller.ts:1260` | | Customer uploads the duty/tax payment slip | `POST` | `/api/contracts/bookings/:bookingId/duty-slip` | `modules/contracts/contracts.controller.ts:1455` | | GL DJ raises the post-offload final invoice (amount + invoice document) | `POST` | `/api/contracts/bookings/:bookingId/final-invoice` | `modules/contracts/contracts.controller.ts:1332` | | Customer attaches the payment slip for the final invoice | `POST` | `/api/contracts/bookings/:bookingId/final-invoice-slip` | `modules/contracts/contracts.controller.ts:1374` | | Customer approves the drafted final invoice — unlocks the payment slip | `POST` | `/api/contracts/bookings/:bookingId/final-invoice/approve` | `modules/contracts/contracts.controller.ts:1359` | | GL (ET or DJ) confirms the payment slip — settles the final invoice | `POST` | `/api/contracts/bookings/:bookingId/final-invoice/confirm` | `modules/contracts/contracts.controller.ts:1386` | | GL DJ logs a cargo exception with photo evidence | `POST` | `/api/contracts/bookings/:bookingId/incidents` | `modules/contracts/contracts.controller.ts:1479` | | GL / Ops / Terminal marks a post-booking milestone complete | `POST` | `/api/contracts/bookings/:bookingId/milestones/:code/complete` | `modules/contracts/contracts.controller.ts:1205` | | GL ET assigns a customs risk level (GREEN/YELLOW/RED) | `POST` | `/api/contracts/bookings/:bookingId/risk` | `modules/contracts/contracts.controller.ts:1241` | | GL ET advises (or skips) the post-arrival additional duty/tax round (import) | `POST` | `/api/contracts/bookings/:bookingId/second-duty` | `modules/contracts/contracts.controller.ts:1399` | | Customer attaches the additional duty/tax payment slip | `POST` | `/api/contracts/bookings/:bookingId/second-duty-slip` | `modules/contracts/contracts.controller.ts:1429` | | GL station manager routes the shipment + binds staff | `POST` | `/api/contracts/bookings/:bookingId/station-assign` | `modules/contracts/contracts.controller.ts:1276` | | Close (accept) the T1 set — GL ET after arrival (import) / GL DJ after gate pass (export) | `POST` | `/api/contracts/bookings/:bookingId/t1-close` | `modules/contracts/contracts.controller.ts:1316` | | GL Djibouti uploads T1 transit documents (multi-file) after wagon allocation; locked once the train departs | `POST` | `/api/contracts/bookings/:bookingId/t1-documents` | `modules/contracts/contracts.controller.ts:1301` | | GL ET uploads export transit permit documents (multi-file) | `POST` | `/api/contracts/bookings/:bookingId/transport-document` | `modules/contracts/contracts.controller.ts:1289` | | Share a document with the other GL desk | `POST` | `/api/gl-exchange/:entityId` | `modules/contracts/gl-exchange.controller.ts:59` | | Edit this contract\'s document articles only (per-contract; never touches the six shared templates) | `PUT` | `/api/contracts/:id/document/articles` | `modules/contracts/contracts.controller.ts:441` | | Update contract | `PATCH` | `/api/contracts/:id` | `modules/contracts/contracts.controller.ts:327` | | Uploader edits a shared document (title, visibility, file) | `PATCH` | `/api/gl-exchange/documents/:documentId` | `modules/contracts/gl-exchange.controller.ts:79` | | Soft-delete DRAFT contract | `DELETE` | `/api/contracts/:id` | `modules/contracts/contracts.controller.ts:346` | | Uploader removes a shared document | `DELETE` | `/api/gl-exchange/documents/:documentId` | `modules/contracts/gl-exchange.controller.ts:105` | ### Contract Template | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a bulk contract template for a (cargo type, customs option) pair | `POST` | `/api/contract-templates` | `modules/contract-templates/contract-templates.controller.ts:56` | | Add an article to the template | `POST` | `/api/contract-templates/:code/articles` | `modules/contract-templates/contract-templates.controller.ts:118` | | Render an HTML preview of the template against mock contract data | `POST` | `/api/contract-templates/:code/preview` | `modules/contract-templates/contract-templates.controller.ts:97` | | Replace the full ordered article list (used for reorder) | `PUT` | `/api/contract-templates/:code/articles` | `modules/contract-templates/contract-templates.controller.ts:111` | | Update template metadata (name, title, recitals, active flag) | `PATCH` | `/api/contract-templates/:code` | `modules/contract-templates/contract-templates.controller.ts:77` | | Update an article's title or body | `PATCH` | `/api/contract-templates/:code/articles/:articleId` | `modules/contract-templates/contract-templates.controller.ts:125` | | Delete a staff-created bulk template (system templates refuse) | `DELETE` | `/api/contract-templates/:code` | `modules/contract-templates/contract-templates.controller.ts:84` | | Remove an article from the template | `DELETE` | `/api/contract-templates/:code/articles/:articleId` | `modules/contract-templates/contract-templates.controller.ts:136` | ### Driver | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new driver | `POST` | `/api/drivers` | `modules/drivers/drivers.controller.ts:41` | | Upload driver documents (code driver_docs) | `POST` | `/api/drivers/:id/documents` | `modules/drivers/drivers.controller.ts:80` | | Update a driver | `PATCH` | `/api/drivers/:id` | `modules/drivers/drivers.controller.ts:128` | | Delete a driver | `DELETE` | `/api/drivers/:id` | `modules/drivers/drivers.controller.ts:138` | | Delete a driver document | `DELETE` | `/api/drivers/:id/documents/:fileId` | `modules/drivers/drivers.controller.ts:121` | ### Dropdown Setting | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new dropdown setting | `POST` | `/api/dropdown-settings` | `modules/dropdown-settings/dropdown-settings.controller.ts:61` | | Append a single option to a setting | `POST` | `/api/dropdown-settings/:id/options` | `modules/dropdown-settings/dropdown-settings.controller.ts:98` | | Replace the full option list for a setting | `PUT` | `/api/dropdown-settings/:id/options` | `modules/dropdown-settings/dropdown-settings.controller.ts:88` | | Update a dropdown setting's metadata | `PATCH` | `/api/dropdown-settings/:id` | `modules/dropdown-settings/dropdown-settings.controller.ts:68` | | Update a single option | `PATCH` | `/api/dropdown-settings/options/:optionId` | `modules/dropdown-settings/dropdown-settings.controller.ts:108` | | Soft-delete a dropdown setting | `DELETE` | `/api/dropdown-settings/:id` | `modules/dropdown-settings/dropdown-settings.controller.ts:78` | | Soft-delete a single option | `DELETE` | `/api/dropdown-settings/options/:optionId` | `modules/dropdown-settings/dropdown-settings.controller.ts:118` | ### EIMS Invoice | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Register the invoice with MoR EIMS. Idempotent — an invoice that already has an IRN is returned unchanged | `POST` | `/api/invoices/:id/eims/register` | `modules/eims/eims-invoice.controller.ts:32` | | Resolve an unacknowledged submission: record the IRN confirmed with MoR, or discard it. Clears the system-wide block | `POST` | `/api/invoices/:id/eims/resolve` | `modules/eims/eims-invoice.controller.ts:49` | | Verify the invoice's stored IRN against EIMS | `POST` | `/api/invoices/:id/eims/verify` | `modules/eims/eims-invoice.controller.ts:42` | ### Exchange Setting | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Set the USD→ETB fallback by hand (used only while CBE is unreachable) | `PATCH` | `/api/exchange-settings` | `modules/exchange-settings/exchange-settings.controller.ts:35` | ### Facility | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new facility | `POST` | `/api/facilities` | `modules/facilities/facilities.controller.ts:22` | | Update a facility | `PATCH` | `/api/facilities/:id` | `modules/facilities/facilities.controller.ts:41` | | Delete a facility (soft delete) | `DELETE` | `/api/facilities/:id` | `modules/facilities/facilities.controller.ts:48` | ### Fayda Verification | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Start a VeriFayda 2.0 verification session | `POST` | `/api/fayda/verification/start` | `modules/verifayda/verifayda.controller.ts:44` | ### File Upload Setting | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new file upload setting | `POST` | `/api/file-upload-settings` | `modules/file-upload-settings/file-upload-settings.controller.ts:56` | | Append a single field to a setting | `POST` | `/api/file-upload-settings/:id/fields` | `modules/file-upload-settings/file-upload-settings.controller.ts:93` | | Replace the full field list for a setting | `PUT` | `/api/file-upload-settings/:id/fields` | `modules/file-upload-settings/file-upload-settings.controller.ts:83` | | Update a file upload setting's metadata | `PATCH` | `/api/file-upload-settings/:id` | `modules/file-upload-settings/file-upload-settings.controller.ts:63` | | Update a single field | `PATCH` | `/api/file-upload-settings/fields/:fieldId` | `modules/file-upload-settings/file-upload-settings.controller.ts:103` | | Soft-delete a file upload setting | `DELETE` | `/api/file-upload-settings/:id` | `modules/file-upload-settings/file-upload-settings.controller.ts:73` | | Soft-delete a single field | `DELETE` | `/api/file-upload-settings/fields/:fieldId` | `modules/file-upload-settings/file-upload-settings.controller.ts:113` | ### First Mile | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a first-mile leg | `POST` | `/api/first-mile` | `modules/first-mile/first-mile.controller.ts:84` | | Set per-vehicle actual distances (does not generate an invoice) | `POST` | `/api/first-mile/:id/distances` | `modules/first-mile/first-mile.controller.ts:124` | | Generate the first-mile delivery-fee invoice | `POST` | `/api/first-mile/:id/invoice` | `modules/first-mile/first-mile.controller.ts:100` | | Set the vehicles assigned to a first-mile pickup (multi-truck) | `POST` | `/api/first-mile/:id/vehicles` | `modules/first-mile/first-mile.controller.ts:114` | | Accept a paid booking and create a first-mile leg | `POST` | `/api/first-mile/accept/:reference` | `modules/first-mile/first-mile.controller.ts:77` | | Update a first-mile leg | `PATCH` | `/api/first-mile/:id` | `modules/first-mile/first-mile.controller.ts:91` | | Soft-delete a first-mile leg | `DELETE` | `/api/first-mile/:id` | `modules/first-mile/first-mile.controller.ts:134` | ### Fuel | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Record fuel purchase | `POST` | `/api/fuel/purchases` | `modules/fuel/fuel.controller.ts:22` | ### GPS Tracking | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Register a GPS tracker | `POST` | `/api/gps/devices` | `modules/gps-tracking/gps-tracking.controller.ts:52` | | Update a GPS tracker (name / assigned vehicle) | `PATCH` | `/api/gps/devices/:id` | `modules/gps-tracking/gps-tracking.controller.ts:59` | | Delete a GPS tracker | `DELETE` | `/api/gps/devices/:id` | `modules/gps-tracking/gps-tracking.controller.ts:66` | ### Import Operation | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Batch 12: record declaration serial number | `POST` | `/api/import-operations/customs/:bookingId/declaration` | `modules/import-operations/import-operations.controller.ts:53` | | Batch 12: upload IM4/IM5/T1/permit/payment-slip documents | `POST` | `/api/import-operations/customs/:bookingId/documents` | `modules/import-operations/import-operations.controller.ts:44` | | Batch 12: mark duties and taxes paid | `POST` | `/api/import-operations/customs/:bookingId/duties-taxes-paid` | `modules/import-operations/import-operations.controller.ts:71` | | Batch 12: notify duties and taxes | `POST` | `/api/import-operations/customs/:bookingId/notify-duties-taxes` | `modules/import-operations/import-operations.controller.ts:62` | | Batch 12: mark import release permitted | `POST` | `/api/import-operations/customs/:bookingId/release-permitted` | `modules/import-operations/import-operations.controller.ts:86` | | Batch 12: assign customs risk | `POST` | `/api/import-operations/customs/:bookingId/risk` | `modules/import-operations/import-operations.controller.ts:80` | | Batch 8: report a Djibouti import incident / exception | `POST` | `/api/import-operations/djibouti-incidents` | `modules/import-operations/import-operations.controller.ts:32` | | Batch 16: create an empty container return record | `POST` | `/api/import-operations/empty-container-returns` | `modules/import-operations/import-operations.controller.ts:101` | | Batch 16: advance empty container return workflow | `POST` | `/api/import-operations/empty-container-returns/:id/status` | `modules/import-operations/import-operations.controller.ts:107` | ### Incident | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Report an incident | `POST` | `/api/incidents` | `modules/incidents/incidents.controller.ts:36` | | Update an incident | `PATCH` | `/api/incidents/:id` | `modules/incidents/incidents.controller.ts:72` | | Delete an incident | `DELETE` | `/api/incidents/:id` | `modules/incidents/incidents.controller.ts:79` | ### Interchange Document | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Generate interchange document from a train schedule handover | `POST` | `/api/interchange-documents/generate-from-schedule` | `modules/interchange-documents/interchange-documents.controller.ts:41` | | Acknowledge an interchange document | `PATCH` | `/api/interchange-documents/:id/acknowledge` | `modules/interchange-documents/interchange-documents.controller.ts:48` | | Dispute an interchange document | `PATCH` | `/api/interchange-documents/:id/dispute` | `modules/interchange-documents/interchange-documents.controller.ts:58` | ### Last Mile | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a last-mile leg | `POST` | `/api/last-mile` | `modules/last-mile/last-mile.controller.ts:97` | | Set each truck\'s own detention window (arrived at destination / returned) | `POST` | `/api/last-mile/:id/detention-times` | `modules/last-mile/last-mile.controller.ts:142` | | Set per-vehicle actual distances (does not generate an invoice) | `POST` | `/api/last-mile/:id/distances` | `modules/last-mile/last-mile.controller.ts:132` | | Generate the delivery-fee invoice for a last-mile leg | `POST` | `/api/last-mile/:id/invoice` | `modules/last-mile/last-mile.controller.ts:179` | | Record proof of delivery (signature + photos) and complete the leg | `POST` | `/api/last-mile/:id/proof-of-delivery` | `modules/last-mile/last-mile.controller.ts:166` | | Set the vehicles assigned to a last-mile delivery (multi-truck) | `POST` | `/api/last-mile/:id/vehicles` | `modules/last-mile/last-mile.controller.ts:122` | | Set each truck\'s warehouse gate arrival/departure times | `POST` | `/api/last-mile/:id/warehouse-gate-times` | `modules/last-mile/last-mile.controller.ts:154` | | Accept a paid booking and create a last-mile leg | `POST` | `/api/last-mile/accept/:reference` | `modules/last-mile/last-mile.controller.ts:90` | | Update a last-mile leg | `PATCH` | `/api/last-mile/:id` | `modules/last-mile/last-mile.controller.ts:104` | | Soft-delete a last-mile leg | `DELETE` | `/api/last-mile/:id` | `modules/last-mile/last-mile.controller.ts:113` | ### Last Mile Request | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Truck & Machinery chief approves the request — the advance defaults to the live last-mile rate; LM contract becomes signable and the advance invoice follows the customer signature | `POST` | `/api/last-mile-requests/:id/approve` | `modules/last-mile-requests/last-mile-requests.controller.ts:119` | | Customer agrees and signs the LM contract — then the advance invoice is issued | `POST` | `/api/last-mile-requests/:id/contract/sign` | `modules/last-mile-requests/last-mile-requests.controller.ts:83` | | Truck & Machinery chief rejects the request with a reason | `POST` | `/api/last-mile-requests/:id/reject` | `modules/last-mile-requests/last-mile-requests.controller.ts:130` | | Customer confirms which containers go via EDR last-mile | `POST` | `/api/last-mile-requests/:id/submit` | `modules/last-mile-requests/last-mile-requests.controller.ts:108` | ### Locomotive | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a locomotive | `POST` | `/api/locomotives` | `modules/locomotives/locomotives.controller.ts:58` | | Decommission a locomotive | `POST` | `/api/locomotives/:id/decommission` | `modules/locomotives/locomotives.controller.ts:72` | | Update a locomotive | `PATCH` | `/api/locomotives/:id` | `modules/locomotives/locomotives.controller.ts:65` | | Permanently delete a locomotive (irreversible; refused if any train references it) | `DELETE` | `/api/locomotives/:id/permanent` | `modules/locomotives/locomotives.controller.ts:82` | ### Maintenance | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Record maintenance cost | `POST` | `/api/maintenance/costs` | `modules/maintenance/maintenance.controller.ts:38` | | Define/adjust a service interval (e.g. oil change every 10,000 km) | `POST` | `/api/maintenance/intervals` | `modules/maintenance/maintenance.controller.ts:59` | | Create part | `POST` | `/api/maintenance/parts` | `modules/maintenance/maintenance.controller.ts:150` | | Schedule maintenance | `POST` | `/api/maintenance/schedules` | `modules/maintenance/maintenance.controller.ts:31` | | Create warranty | `POST` | `/api/maintenance/warranties` | `modules/maintenance/maintenance.controller.ts:186` | | Create work order | `POST` | `/api/maintenance/work-orders` | `modules/maintenance/maintenance.controller.ts:110` | | Update part | `PATCH` | `/api/maintenance/parts/:id` | `modules/maintenance/maintenance.controller.ts:170` | | Update maintenance schedule | `PATCH` | `/api/maintenance/schedules/:id` | `modules/maintenance/maintenance.controller.ts:45` | | Update work order | `PATCH` | `/api/maintenance/work-orders/:id` | `modules/maintenance/maintenance.controller.ts:134` | | Deactivate a service interval (stops auto-scheduling) | `DELETE` | `/api/maintenance/intervals/:id` | `modules/maintenance/maintenance.controller.ts:73` | | Delete part | `DELETE` | `/api/maintenance/parts/:id` | `modules/maintenance/maintenance.controller.ts:177` | | Delete warranty | `DELETE` | `/api/maintenance/warranties/:id` | `modules/maintenance/maintenance.controller.ts:200` | | Delete work order | `DELETE` | `/api/maintenance/work-orders/:id` | `modules/maintenance/maintenance.controller.ts:141` | ### Notification Inbox | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Mark all my notifications as read | `POST` | `/api/notifications/read-all` | `modules/notification-inbox/notification-inbox.controller.ts:53` | | Mark one of my notifications as read | `PATCH` | `/api/notifications/:id/read` | `modules/notification-inbox/notification-inbox.controller.ts:44` | ### Organization User | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create an organization user without assigning positions | `POST` | `/api/backoffice/organizations/:orgId/users` | `modules/backoffice/backoffice.controller.ts:24` | | Replace org-scoped roles assigned to an employee user | `PUT` | `/api/backoffice/organizations/:orgId/employee-users/:userId/roles` | `modules/backoffice/backoffice.controller.ts:58` | ### OTP | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Send OTP | `POST` | `/api/otp/send` | `modules/otp/otp.controller.ts:41` | | Verify OTP | `POST` | `/api/otp/verify` | `modules/otp/otp.controller.ts:62` | ### Password Reset | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Send a password-reset code to the account's email AND phone | `POST` | `/api/auth/forgot-password/request` | `modules/auth/forgot-password.controller.ts:30` | | Validate a staff-issued reset link and return its set-password ticket | `POST` | `/api/auth/forgot-password/resolve-link` | `modules/auth/forgot-password.controller.ts:73` | | Exchange a valid reset code for a single-use set-password ticket | `POST` | `/api/auth/forgot-password/verify` | `modules/auth/forgot-password.controller.ts:62` | | Send a password-reset link to a customer's primary contact | `POST` | `/api/backoffice/customers/:companyId/reset-password` | `modules/auth/customer-reset.controller.ts:49` | ### Payment | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Finance confirms a USD invoice paid by bank transfer — slip file required, settles the full balance | `POST` | `/api/billing/invoices/:id/confirm-offline` | `modules/billing/billing.controller.ts:81` | | Confirm an OTP-debit payment (CAC Bank) for one of the customer's invoices | `POST` | `/api/billing/my-invoices/:id/confirm` | `modules/billing/portal-billing.controller.ts:102` | | Initiate payment for one of the customer's invoices | `POST` | `/api/billing/my-invoices/:id/pay` | `modules/billing/portal-billing.controller.ts:86` | | Live still-payable check + payer name for a CBE bill (called while CBE is on the line) | `POST` | `/api/internal/payments/bill-query` | `modules/payment/internal-payment.controller.ts:56` | | Apply a payment.succeeded / payment.failed event from the payment service (idempotent) | `POST` | `/api/internal/payments/mark-paid` | `modules/payment/internal-payment.controller.ts:45` | | Initiate payment for an invoice | `POST` | `/api/payments/initiate` | `modules/billing/payment.controller.ts:39` | | Success-redirect ack: mark payment processing + invoice PAYMENT_PROCESSING (webhook remains source of truth) | `POST` | `/api/payments/redirect-success/:bookingId` | `modules/payment/payment.controller.ts:89` | ### Priority Config | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a priority config | `POST` | `/api/priority-configs` | `modules/rule-engine/controllers/priority-configs.controller.ts:51` | | Move a priority config up or down in display order | `POST` | `/api/priority-configs/:id/move-order` | `modules/rule-engine/controllers/priority-configs.controller.ts:66` | | Bulk reorder priority configs by ID list | `POST` | `/api/priority-configs/reorder` | `modules/rule-engine/controllers/priority-configs.controller.ts:58` | | Update a priority config | `PATCH` | `/api/priority-configs/:id` | `modules/rule-engine/controllers/priority-configs.controller.ts:74` | | Soft-delete a priority config | `DELETE` | `/api/priority-configs/:id` | `modules/rule-engine/controllers/priority-configs.controller.ts:81` | ### Priority Rule Change Request | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Submit a priority-rule change for approval | `POST` | `/api/priority-rule-change-requests` | `modules/rule-engine/controllers/priority-rule-change-requests.controller.ts:34` | | Approve and apply a pending change | `POST` | `/api/priority-rule-change-requests/:id/approve` | `modules/rule-engine/controllers/priority-rule-change-requests.controller.ts:52` | | Reject a pending change | `POST` | `/api/priority-rule-change-requests/:id/reject` | `modules/rule-engine/controllers/priority-rule-change-requests.controller.ts:65` | ### Procurement | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create an asset acquisition | `POST` | `/api/procurement/acquisitions` | `modules/procurement/procurement.controller.ts:56` | | Create an asset disposal | `POST` | `/api/procurement/disposals` | `modules/procurement/procurement.controller.ts:90` | | Create a vendor | `POST` | `/api/procurement/vendors` | `modules/procurement/procurement.controller.ts:28` | | Update an asset acquisition | `PATCH` | `/api/procurement/acquisitions/:id` | `modules/procurement/procurement.controller.ts:75` | | Update a vendor | `PATCH` | `/api/procurement/vendors/:id` | `modules/procurement/procurement.controller.ts:41` | | Delete an asset acquisition | `DELETE` | `/api/procurement/acquisitions/:id` | `modules/procurement/procurement.controller.ts:82` | | Delete an asset disposal | `DELETE` | `/api/procurement/disposals/:id` | `modules/procurement/procurement.controller.ts:103` | | Delete a vendor | `DELETE` | `/api/procurement/vendors/:id` | `modules/procurement/procurement.controller.ts:48` | ### Rate | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a rate (DRAFT) | `POST` | `/api/rates` | `modules/rule-engine/controllers/rates.controller.ts:46` | | CEO approves a rate | `POST` | `/api/rates/:id/approve` | `modules/rule-engine/controllers/rates.controller.ts:70` | | Submit rate for CEO approval | `POST` | `/api/rates/:id/submit` | `modules/rule-engine/controllers/rates.controller.ts:63` | | Update a DRAFT rate | `PATCH` | `/api/rates/:id` | `modules/rule-engine/controllers/rates.controller.ts:56` | | Soft-delete a rate | `DELETE` | `/api/rates/:id` | `modules/rule-engine/controllers/rates.controller.ts:82` | ### Rate Change Request | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Propose a change to a LIVE rate | `POST` | `/api/rate-change-requests` | `modules/rule-engine/controllers/rate-change-requests.controller.ts:23` | | Approve a rate change and put it into effect | `POST` | `/api/rate-change-requests/:id/approve` | `modules/rule-engine/controllers/rate-change-requests.controller.ts:37` | | Reject a rate change — the rate keeps its current value | `POST` | `/api/rate-change-requests/:id/reject` | `modules/rule-engine/controllers/rate-change-requests.controller.ts:48` | ### Route | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create route | `POST` | `/api/routes` | `modules/routes/routes.controller.ts:61` | | Update route | `PATCH` | `/api/routes/:id` | `modules/routes/routes.controller.ts:68` | | Deactivate route | `DELETE` | `/api/routes/:id` | `modules/routes/routes.controller.ts:90` | | Permanently delete a route (irreversible; refused while any train schedule references it) | `DELETE` | `/api/routes/:id/permanent` | `modules/routes/routes.controller.ts:79` | ### Schedule | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Reschedule train for maintenance (new departure + rebalance) | `POST` | `/api/train-scheduling/schedules/:id/maintenance` | `modules/scheduling-reschedule/scheduling-reschedule.controller.ts:52` | | Execute a confirmed reschedule plan | `POST` | `/api/train-scheduling/schedules/:id/reschedule/execute` | `modules/scheduling-reschedule/scheduling-reschedule.controller.ts:30` | | Preview reschedule / government preempt plan | `POST` | `/api/train-scheduling/schedules/:id/reschedule/preview` | `modules/scheduling-reschedule/scheduling-reschedule.controller.ts:20` | ### Service Type | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a service type | `POST` | `/api/service-types` | `modules/rule-engine/controllers/service-types.controller.ts:51` | | Move a service type up or down in display order | `POST` | `/api/service-types/:id/move-order` | `modules/rule-engine/controllers/service-types.controller.ts:36` | | Bulk reorder service types by ID list | `POST` | `/api/service-types/reorder` | `modules/rule-engine/controllers/service-types.controller.ts:28` | | Update a service type | `PATCH` | `/api/service-types/:id` | `modules/rule-engine/controllers/service-types.controller.ts:58` | | Soft-delete a service type | `DELETE` | `/api/service-types/:id` | `modules/rule-engine/controllers/service-types.controller.ts:65` | ### Shipping Line | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a shipping line | `POST` | `/api/shipping-lines` | `modules/rule-engine/controllers/shipping-lines.controller.ts:33` | | Update a shipping line | `PATCH` | `/api/shipping-lines/:id` | `modules/rule-engine/controllers/shipping-lines.controller.ts:40` | | Soft-delete a shipping line | `DELETE` | `/api/shipping-lines/:id` | `modules/rule-engine/controllers/shipping-lines.controller.ts:47` | ### Signature | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create or update the reusable saved signature | `PUT` | `/api/me/signature` | `modules/signatures/signatures.controller.ts:23` | ### Support Chat | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Start chatting with a company (returns the thread if one exists) | `POST` | `/api/support/agent/conversations` | `modules/support-chat/support-chat-agent.controller.ts:49` | | Reply as an agent, optionally with attachments | `POST` | `/api/support/agent/conversations/:id/messages` | `modules/support-chat/support-chat-agent.controller.ts:74` | | Mark a thread read (agent side) | `POST` | `/api/support/agent/conversations/:id/read` | `modules/support-chat/support-chat-agent.controller.ts:114` | | Send a message as the customer (optionally with attachments), opening the thread if needed | `POST` | `/api/support/conversation/messages` | `modules/support-chat/support-chat.controller.ts:65` | | Mark my company's thread read (customer side) | `POST` | `/api/support/conversation/read` | `modules/support-chat/support-chat.controller.ts:102` | ### Support Content | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Restore a version — re-saves it as a new version, never destructive | `POST` | `/api/support-content/documents/:slug/versions/:version/restore` | `modules/support-content/support-content.controller.ts:123` | | Upload an image or video for a help section | `POST` | `/api/support-content/media` | `modules/support-content/support-content.controller.ts:55` | | Replace a document's payload, recording a new version | `PATCH` | `/api/support-content/documents/:slug` | `modules/support-content/support-content.controller.ts:93` | ### Train | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Register a new train | `POST` | `/api/trains` | `modules/trains/trains.controller.ts:33` | | Update a train | `PATCH` | `/api/trains/:id` | `modules/trains/trains.controller.ts:52` | | Delete a train | `DELETE` | `/api/trains/:id` | `modules/trains/trains.controller.ts:59` | ### Train Build | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Build a train: code + yard + 2+ locomotives (+ optional wagons) | `POST` | `/api/train-builder` | `modules/trains/train-builder.controller.ts:50` | | Reactivate a deactivated train back to AVAILABLE | `POST` | `/api/train-builder/:id/activate` | `modules/trains/train-builder.controller.ts:158` | | Deactivate the train (park it) — only allowed with no active schedule | `POST` | `/api/train-builder/:id/deactivate` | `modules/trains/train-builder.controller.ts:149` | | Persist a drag-reorder of the full consist | `POST` | `/api/train-builder/:id/reorder-wagons` | `modules/trains/train-builder.controller.ts:142` | | Append AVAILABLE wagons from the train's yard to the consist | `POST` | `/api/train-builder/:id/wagons` | `modules/trains/train-builder.controller.ts:109` | | Detach one wagon and move it to MAINTENANCE status | `POST` | `/api/train-builder/:id/wagons/:wagonId/maintenance` | `modules/trains/train-builder.controller.ts:131` | | Replace the locomotive set (minimum 1, same yard) | `PUT` | `/api/train-builder/:id/locomotives` | `modules/trains/train-builder.controller.ts:78` | | Edit the train's name and fixed import/export run numbers | `PATCH` | `/api/train-builder/:id/details` | `modules/trains/train-builder.controller.ts:88` | | Relocate the train — its locomotives and wagons move to the new yard with it | `PATCH` | `/api/train-builder/:id/yard` | `modules/trains/train-builder.controller.ts:100` | | Disband the train (release wagons and locomotives) | `DELETE` | `/api/train-builder/:id` | `modules/trains/train-builder.controller.ts:165` | | Detach one wagon from the consist | `DELETE` | `/api/train-builder/:id/wagons/:wagonId` | `modules/trains/train-builder.controller.ts:120` | ### Train Schedule | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Staff: place a paid booking onto a fitting train (notifies customer on date change) | `POST` | `/api/train-scheduling/bookings/:bookingId/allocate` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:880` | | Staff: expire a reservation and free its capacity | `POST` | `/api/train-scheduling/bookings/:bookingId/expire` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:845` | | Staff: mark a reserved booking paid and allocate it now | `POST` | `/api/train-scheduling/bookings/:bookingId/mark-paid` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:835` | | Re-point a booking to another OPEN same-route schedule | `POST` | `/api/train-scheduling/bookings/:bookingId/move-schedule` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:855` | | Preview a bulk train schedule | `POST` | `/api/train-scheduling/bulk/preview` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:302` | | Create a bulk train schedule | `POST` | `/api/train-scheduling/bulk/schedules` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:316` | | Assign bulk bookings to a train schedule | `POST` | `/api/train-scheduling/bulk/schedules/:id/assign-bookings` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:349` | | Cancel bulk train schedule | `POST` | `/api/train-scheduling/bulk/schedules/:id/cancel` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:976` | | Preview a container train schedule | `POST` | `/api/train-scheduling/container/preview` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:295` | | Create a container train schedule | `POST` | `/api/train-scheduling/container/schedules` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:309` | | Assign container bookings to a train schedule | `POST` | `/api/train-scheduling/container/schedules/:id/assign-bookings` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:335` | | Cancel container train schedule | `POST` | `/api/train-scheduling/container/schedules/:id/cancel` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:969` | | Preview a mixed-capable train schedule | `POST` | `/api/train-scheduling/preview` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:288` | | Permanently trim free wagons off / couple yard wagons onto the schedule's built train (weight & length limits incl. tolerance enforced, every change logged) | `POST` | `/api/train-scheduling/schedules/:id/adjust-consist` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:197` | | Mark a dispatched train arrived (move assets to destination yard, free assets) | `POST` | `/api/train-scheduling/schedules/:id/arrive` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:915` | | Assign bookings to a train schedule (mixed-capable) | `POST` | `/api/train-scheduling/schedules/:id/assign-bookings` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:323` | | Assign one linked unallocated booking to wagons (preserves existing assignments) | `POST` | `/api/train-scheduling/schedules/:id/assign-unassigned-booking` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:423` | | Confirm a booking's cargo loaded at its origin yard (any direction; train must be at that yard) | `POST` | `/api/train-scheduling/schedules/:id/bookings/:bookingId/load` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:564` | | Confirm a booking's cargo unloaded at its destination yard — per-booking arrival, may precede the train's final arrival | `POST` | `/api/train-scheduling/schedules/:id/bookings/:bookingId/unload` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:577` | | Log the train passing a station (final station triggers arrival) | `POST` | `/api/train-scheduling/schedules/:id/checkpoints` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:903` | | Confirm cargo loaded on the train (any direction; unblocks import-Djibouti dispatch) | `POST` | `/api/train-scheduling/schedules/:id/confirm-loading` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:662` | | Dispatch a scheduled train | `POST` | `/api/train-scheduling/schedules/:id/dispatch` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:514` | | Staff finished document review early — run the batch/payment phase now (applies to the whole route-day group) | `POST` | `/api/train-scheduling/schedules/:id/doc-review-complete` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:824` | | Finalize a draft train schedule | `POST` | `/api/train-scheduling/schedules/:id/finalize` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:507` | | Depart loaded import train from Djibouti | `POST` | `/api/train-scheduling/schedules/:id/import-djibouti/depart` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:675` | | Upload/check an import Djibouti-side document | `POST` | `/api/train-scheduling/schedules/:id/import-djibouti/documents` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:622` | | Mark import Djibouti gatepass permission granted | `POST` | `/api/train-scheduling/schedules/:id/import-djibouti/gatepass-granted` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:632` | | Generate import load list / marshalling document summary | `POST` | `/api/train-scheduling/schedules/:id/import-djibouti/load-list` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:685` | | Confirm import cargo loaded on train at Djibouti | `POST` | `/api/train-scheduling/schedules/:id/import-djibouti/loaded-on-train` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:652` | | Mark import train ready for loading at Djibouti | `POST` | `/api/train-scheduling/schedules/:id/import-djibouti/ready-for-loading` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:642` | | Confirm intercity cargo loaded (train must be at the booking's origin yard) | `POST` | `/api/train-scheduling/schedules/:id/intercity/:bookingId/load` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:590` | | Confirm intercity cargo unloaded at the booking's destination yard (completes the booking) | `POST` | `/api/train-scheduling/schedules/:id/intercity/:bookingId/unload` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:602` | | Accept intercity bookings onto this train (opens their pay window; capacity re-checked per booking) | `POST` | `/api/train-scheduling/schedules/:id/intercity/accept` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:541` | | Maintenance reschedule: move the train to a new departure with every allocated booking aboard — links, wagons and window settings unchanged | `POST` | `/api/train-scheduling/schedules/:id/maintenance` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:798` | | Pin physical wagons to train set slots | `POST` | `/api/train-scheduling/schedules/:id/pin-wagons` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:500` | | Run wagon-level allocation for all eligible linked bookings | `POST` | `/api/train-scheduling/schedules/:id/run-allocation` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:747` | | Manually run the batch fill for a schedule | `POST` | `/api/train-scheduling/schedules/:id/run-batch` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:739` | | Switch out commercial bookings to allocate a government booking in their place | `POST` | `/api/train-scheduling/schedules/:id/switch-government-booking` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:439` | | Move a wagon's whole load to another wagon (empty → move/repin, loaded → swap loads) | `POST` | `/api/train-scheduling/schedules/:id/wagons/:wagonId/move-load` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:402` | | Update global train scheduling rules (singleton) | `PATCH` | `/api/train-scheduling/global-rules` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:124` | | Open or close a schedule booking window | `PATCH` | `/api/train-scheduling/schedules/:id/booking-window` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:756` | | Update a container number on a wagon slot | `PATCH` | `/api/train-scheduling/schedules/:id/container-items/:itemId` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:391` | | Mark import bookings loaded/unloaded on this schedule (tracking only, does not affect dispatch) | `PATCH` | `/api/train-scheduling/schedules/:id/import-loading-status` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:474` | | Mark bookings loaded/unloaded on this schedule (any direction, pre-dispatch only) | `PATCH` | `/api/train-scheduling/schedules/:id/loading-status` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:487` | | Reschedule a train's departure date — only before the booking window opens, and only if the new date still leaves room for the booking lead window | `PATCH` | `/api/train-scheduling/schedules/:id/schedule-date` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:784` | | Override the booking-window rule for one schedule (open/close hour, duration, doc-review, payment, lead days) — only before the window opens | `PATCH` | `/api/train-scheduling/schedules/:id/window-rule` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:770` | | Unassign a booking from a train schedule | `DELETE` | `/api/train-scheduling/schedules/:id/bookings/:bookingId` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:363` | | Remove an empty wagon slot from a train | `DELETE` | `/api/train-scheduling/schedules/:id/wagons/:trainSetWagonId` | `modules/train-scheduling/controllers/train-scheduling.controller.ts:378` | ### Transit Agent | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a transit agent | `POST` | `/api/transit-agents` | `modules/transit-agents/transit-agents.controller.ts:66` | | Update a transit agent | `PATCH` | `/api/transit-agents/:id` | `modules/transit-agents/transit-agents.controller.ts:73` | | Soft-delete a transit agent | `DELETE` | `/api/transit-agents/:id` | `modules/transit-agents/transit-agents.controller.ts:80` | ### Truck Type | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a truck type | `POST` | `/api/truck-types` | `modules/truck-types/truck-types.controller.ts:58` | | Update a truck type | `PATCH` | `/api/truck-types/:id` | `modules/truck-types/truck-types.controller.ts:65` | | Soft-delete a truck type | `DELETE` | `/api/truck-types/:id` | `modules/truck-types/truck-types.controller.ts:72` | ### User Trade Access | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Set the trade directions a backoffice user may see | `PUT` | `/api/user-trade-access/:userId` | `modules/user-trade-access/user-trade-access.controller.ts:45` | ### Vehicle | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new vehicle | `POST` | `/api/vehicles` | `modules/vehicles/vehicles.controller.ts:37` | | Update a vehicle | `PATCH` | `/api/vehicles/:id` | `modules/vehicles/vehicles.controller.ts:78` | | Delete a vehicle | `DELETE` | `/api/vehicles/:id` | `modules/vehicles/vehicles.controller.ts:88` | ### Wagon | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a new wagon | `POST` | `/api/wagons` | `modules/wagons/wagons.controller.ts:39` | | Assign wagon to a train | `POST` | `/api/wagons/:id/assign-train` | `modules/wagons/wagons.controller.ts:100` | | Unassign wagon from train | `POST` | `/api/wagons/:id/unassign-train` | `modules/wagons/wagons.controller.ts:107` | | Set the status of multiple wagons (audited in wagon_status_logs) | `POST` | `/api/wagons/bulk-status` | `modules/wagons/wagons.controller.ts:121` | | Transfer multiple wagons to a destination yard | `POST` | `/api/wagons/bulk-transfer` | `modules/wagons/wagons.controller.ts:114` | | Update a wagon | `PATCH` | `/api/wagons/:id` | `modules/wagons/wagons.controller.ts:71` | | Delete a wagon | `DELETE` | `/api/wagons/:id` | `modules/wagons/wagons.controller.ts:93` | | Permanently delete a wagon (irreversible; refused if it has movements, containers or train-set slots) | `DELETE` | `/api/wagons/:id/permanent` | `modules/wagons/wagons.controller.ts:82` | ### Wagon Transfer Request | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | File a count-only wagon-transfer request | `POST` | `/api/wagon-transfer-requests` | `modules/wagons/wagon-transfer-requests.controller.ts:50` | | Withdraw a request that has not moved any wagon yet (use close-short once wagons have moved) | `POST` | `/api/wagon-transfer-requests/:id/cancel` | `modules/wagons/wagon-transfer-requests.controller.ts:167` | | OCC: end the request with fewer wagons than asked for — what moved stays, the requester is told the shortfall | `POST` | `/api/wagon-transfer-requests/:id/close-short` | `modules/wagons/wagon-transfer-requests.controller.ts:153` | | OCC: pick wagons and execute the transfer | `POST` | `/api/wagon-transfer-requests/:id/fulfill` | `modules/wagons/wagon-transfer-requests.controller.ts:142` | | OCC: accept-and-execute a subset of pending requests (auto-picks available wagons; the rest stay PENDING) | `POST` | `/api/wagon-transfer-requests/bulk-fulfill` | `modules/wagons/wagon-transfer-requests.controller.ts:73` | ### Wagon Type | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a wagon type | `POST` | `/api/wagon-types` | `modules/wagon-types/wagon-types.controller.ts:53` | | Update a wagon type | `PATCH` | `/api/wagon-types/:id` | `modules/wagon-types/wagon-types.controller.ts:60` | | Soft-delete a wagon type | `DELETE` | `/api/wagon-types/:id` | `modules/wagon-types/wagon-types.controller.ts:67` | ### Warehouse | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a warehouse allocation rule | `POST` | `/api/warehouse-allocation-rules` | `modules/warehouses/warehouse-rules.controller.ts:33` | | Preview the yard/warehouse/zone a booking would be allocated to | `POST` | `/api/warehouse-allocation/preview` | `modules/warehouses/warehouse-rules.controller.ts:55` | | Create a storage / demurrage fee rule | `POST` | `/api/warehouse-fee-rules` | `modules/warehouses/warehouse-rules.controller.ts:70` | | Acknowledge / snooze an item fee-accrual alert | `POST` | `/api/warehouse-fees/accrual/:inventoryId/acknowledge` | `modules/warehouses/warehouse-rules.controller.ts:106` | | Create warehouse | `POST` | `/api/warehouses` | `modules/warehouses/warehouses.controller.ts:51` | | Create a yard within a warehouse | `POST` | `/api/warehouses/:warehouseId/yards` | `modules/warehouses/warehouses.controller.ts:78` | | Update a warehouse allocation rule | `PATCH` | `/api/warehouse-allocation-rules/:id` | `modules/warehouses/warehouse-rules.controller.ts:40` | | Update a fee rule | `PATCH` | `/api/warehouse-fee-rules/:id` | `modules/warehouses/warehouse-rules.controller.ts:77` | | Update warehouse | `PATCH` | `/api/warehouses/:id` | `modules/warehouses/warehouses.controller.ts:64` | | Delete a warehouse allocation rule | `DELETE` | `/api/warehouse-allocation-rules/:id` | `modules/warehouses/warehouse-rules.controller.ts:47` | | Delete a fee rule | `DELETE` | `/api/warehouse-fee-rules/:id` | `modules/warehouses/warehouse-rules.controller.ts:84` | | Remove an accrual acknowledgement (re-surface for alerts) | `DELETE` | `/api/warehouse-fees/accrual/:inventoryId/acknowledge` | `modules/warehouses/warehouse-rules.controller.ts:119` | ### Warehouse Fee Invoice | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Generate a truck-detention invoice for a last-mile leg (per truck per day) | `POST` | `/api/last-mile/:id/generate-truck-detention-invoice` | `modules/warehouses/warehouse-invoice.controller.ts:28` | | Record a payment against a warehouse fee invoice | `POST` | `/api/warehouse-fee-invoices/:id/pay` | `modules/warehouses/warehouse-invoice.controller.ts:109` | | Initiate Telebirr/Waafi payment for a warehouse fee invoice | `POST` | `/api/warehouse-fee-invoices/:id/pay-online` | `modules/warehouses/warehouse-invoice.controller.ts:116` | | Generate a warehouse fee invoice from Batch 5 fee calculation | `POST` | `/api/warehouse-inventory/:id/generate-fee-invoice` | `modules/warehouses/warehouse-invoice.controller.ts:20` | | Cancel a warehouse fee invoice | `PATCH` | `/api/warehouse-fee-invoices/:id/cancel` | `modules/warehouses/warehouse-invoice.controller.ts:102` | ### Warehouse Inspection Report | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Upload inspection images / documents | `POST` | `/api/warehouse-inspection-reports/:id/attachments` | `modules/warehouses/warehouse-inspection.controller.ts:68` | | Create an inspection / damage report for an inventory item | `POST` | `/api/warehouse-inventory/:inventoryId/inspection-reports` | `modules/warehouses/warehouse-inspection.controller.ts:37` | | Update an inspection report | `PATCH` | `/api/warehouse-inspection-reports/:id` | `modules/warehouses/warehouse-inspection.controller.ts:61` | ### Warehouse Inventory | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Deliver import goods to the customer + capture proof of delivery | `POST` | `/api/warehouse-inventory/:id/deliver` | `modules/warehouses/warehouse-inventory.controller.ts:594` | | Final terminal release / gate clearance (blocked while fees unpaid) | `POST` | `/api/warehouse-inventory/:id/gate-clearance` | `modules/warehouses/warehouse-inventory.controller.ts:219` | | Load READY_FOR_LOADING inventory onto a wagon | `POST` | `/api/warehouse-inventory/:id/load` | `modules/warehouses/warehouse-inventory.controller.ts:384` | | Move inventory to another warehouse/yard/zone | `POST` | `/api/warehouse-inventory/:id/move` | `modules/warehouses/warehouse-inventory.controller.ts:359` | | Mark reserved inventory READY_FOR_LOADING | `POST` | `/api/warehouse-inventory/:id/ready-for-loading` | `modules/warehouses/warehouse-inventory.controller.ts:373` | | Mark inspected IMPORT inventory READY_FOR_PICKUP | `POST` | `/api/warehouse-inventory/:id/ready-for-pickup` | `modules/warehouses/warehouse-inventory.controller.ts:391` | | Issue a DO / release order for ready-for-pickup inventory | `POST` | `/api/warehouse-inventory/:id/release` | `modules/warehouses/warehouse-inventory.controller.ts:402` | | Mark received inventory as STORED (optional explicit warehouse/yard/zone) | `POST` | `/api/warehouse-inventory/:id/store` | `modules/warehouses/warehouse-inventory.controller.ts:366` | | Auto-load READY_FOR_LOADING inventory with PAID bookings | `POST` | `/api/warehouse-inventory/auto-load-ready` | `modules/warehouses/warehouse-inventory.controller.ts:125` | | Bulk auto-unload all arrived bookings into the warehouse | `POST` | `/api/warehouse-inventory/auto-unload-arrived` | `modules/warehouses/warehouse-inventory.controller.ts:118` | | Approve delivery — customer records their full name (signature optional) | `POST` | `/api/warehouse-inventory/bookings/:bookingId/approve-delivery` | `modules/warehouses/warehouse-inventory.controller.ts:470` | | Ask the customer to sign the handover (creates one if none, then notifies) | `POST` | `/api/warehouse-inventory/bookings/:bookingId/request-handover-signature` | `modules/warehouses/warehouse-inventory.controller.ts:509` | | Unload a single arrived booking into a location | `POST` | `/api/warehouse-inventory/bookings/:bookingId/unload` | `modules/warehouses/warehouse-inventory.controller.ts:209` | | Bulk-dispatch loaded EXPORT inventory (LOADED → DISPATCHED) | `POST` | `/api/warehouse-inventory/bulk-dispatch-export` | `modules/warehouses/warehouse-inventory.controller.ts:195` | | Bulk mark received inventory inspection PASSED (EXPORT → READY_FOR_LOADING) | `POST` | `/api/warehouse-inventory/bulk-mark-inspected` | `modules/warehouses/warehouse-inventory.controller.ts:202` | | Unload all eligible export items assigned to an arrived Djibouti-side train | `POST` | `/api/warehouse-inventory/export/auto-unload-at-djibouti` | `modules/warehouses/warehouse-inventory.controller.ts:294` | | Customer signs one handover (EDR last-mile: one signature per truck) | `POST` | `/api/warehouse-inventory/handovers/:handoverId/sign` | `modules/warehouses/warehouse-inventory.controller.ts:493` | | Unload all eligible assigned bookings of an ARRIVED import train (→ UNLOADED) | `POST` | `/api/warehouse-inventory/import/auto-unload-arrived-bookings` | `modules/warehouses/warehouse-inventory.controller.ts:244` | | Receive inventory at a warehouse location | `POST` | `/api/warehouse-inventory/receive` | `modules/warehouses/warehouse-inventory.controller.ts:322` | | Bulk-receive selected eligible PAID bookings into a location | `POST` | `/api/warehouse-inventory/receive-bulk` | `modules/warehouses/warehouse-inventory.controller.ts:140` | | Reserve stored inventory for a PAID booking | `POST` | `/api/warehouse-inventory/reserve` | `modules/warehouses/warehouse-inventory.controller.ts:330` | | Load selected inventory items onto their allocated wagons for a train | `POST` | `/api/warehouse-inventory/train/:scheduleId/load` | `modules/warehouses/warehouse-inventory.controller.ts:184` | | Mark loaded inventory DISPATCHED (left the terminal) | `PATCH` | `/api/warehouse-inventory/:id/dispatch` | `modules/warehouses/warehouse-inventory.controller.ts:602` | | Record Yes/No double handling after unloading (Yes applies the double-handling fee rule) | `PATCH` | `/api/warehouse-inventory/bookings/:bookingId/double-handling` | `modules/warehouses/warehouse-inventory.controller.ts:556` | ### Warehouse Yard | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a zone within a yard | `POST` | `/api/warehouse-yards/:yardId/zones` | `modules/warehouses/warehouse-yards.controller.ts:50` | | Update warehouse yard | `PATCH` | `/api/warehouse-yards/:id` | `modules/warehouses/warehouse-yards.controller.ts:36` | ### Warehouse Zone | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Update warehouse zone | `PATCH` | `/api/warehouse-zones/:id` | `modules/warehouses/warehouse-zones.controller.ts:37` | ### Weight Limit Rule | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a weight limit rule | `POST` | `/api/weight-limit-rules` | `modules/rule-engine/controllers/weight-limit-rules.controller.ts:32` | | Update a weight limit rule | `PATCH` | `/api/weight-limit-rules/:id` | `modules/rule-engine/controllers/weight-limit-rules.controller.ts:39` | | Soft-delete a weight limit rule | `DELETE` | `/api/weight-limit-rules/:id` | `modules/rule-engine/controllers/weight-limit-rules.controller.ts:46` | ### Yard | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a yard | `POST` | `/api/yards` | `modules/rule-engine/controllers/yards.controller.ts:53` | | Move a yard up or down in display order | `POST` | `/api/yards/:id/move-order` | `modules/rule-engine/controllers/yards.controller.ts:38` | | Bulk reorder yards by ID list | `POST` | `/api/yards/reorder` | `modules/rule-engine/controllers/yards.controller.ts:30` | | Update a yard | `PATCH` | `/api/yards/:id` | `modules/rule-engine/controllers/yards.controller.ts:60` | | Soft-delete a yard | `DELETE` | `/api/yards/:id` | `modules/rule-engine/controllers/yards.controller.ts:67` | ### Yard Distance | Title | Method | Endpoint | Source | | --- | --- | --- | --- | | Create a yard distance | `POST` | `/api/yard-distances` | `modules/rule-engine/controllers/yard-distances.controller.ts:42` | | Update a yard distance | `PATCH` | `/api/yard-distances/:id` | `modules/rule-engine/controllers/yard-distances.controller.ts:49` | | Soft-delete a yard distance | `DELETE` | `/api/yard-distances/:id` | `modules/rule-engine/controllers/yard-distances.controller.ts:56` |