Skip to main content
Every order that reaches secured gets one commercial invoice, owned and issued by LMN. It is the amount the partner owes LMN for that order — the settlement document that was previously shared out-of-band as a payment-due report. Four read-only routes expose it; nothing about an invoice is mutable through the partner API. Every order response also carries an invoice summary (null when none), and issuing fires the invoice.issued webhook.

Lifecycle

  • draft — created automatically the moment the order transitions to secured. Drafts are visible on every route above (and as Order.invoice with status: draft), with number: null and document_url: null. Draft amounts track the order and may change between reads — treat them as indicative until issued.
  • issued — LMN ops reviewed the draft, entered the consignee and shipment month, and published it: the number is assigned, version becomes 1, the PDF is available, and invoice.issued fires. Amounts are frozen.
  • Re-issue — LMN may correct an issued (or paid) invoice, e.g. to complete the packing list once the container is loaded. The number never changes; version increments, a new PDF is published, and invoice.issued fires again with data.previous_version. Earlier versions’ PDFs remain downloadable.
  • paid — LMN ops recorded the payment (paid_at). No webhook — read it from Order.invoice or these routes.
  • void — terminal. The record stays readable with void_reason; a new draft may then be created for the same order and receives the next number on issue. No webhook.
One live invoice per order. GET /v1/orders/{id}/invoice and Order.invoice always return the order’s newest invoice, so after a void you see the voided record until LMN creates a fresh draft.

Invoice numbers

{prefix}_{YYYY}_{MM}_{seq} — a per-partner prefix, the four-digit year and two-digit month of shipment_month, and a sequence per (partner, environment, shipment month) starting at 001: SKL_2026_09_001, SKL_2026_09_002, … The sequence may exceed three digits (_1000) and is never zero-padded beyond three. Sandbox and production sequences are independent, so the same number can exist in both environments. Gaps are possible (a numbered draft that was voided) and carry no meaning.

Pricing is bundled

amounts.price is one figure. LMN’s commission and the partner discount from pricing.discount_config are realised inside it — against the actual hammer price, which may be lower than max_bid_amount_usd — but are not itemised on the API or the PDF, exactly as on the paper invoice. ocean_freight appears as its own line only when LMN lists it separately (otherwise it is inside price); insurance is an optional additional line. total = price + ocean_freight + insurance. Amounts are numbers in major units with at most 2 decimals, unlike the whole-USD integers on Order.amounts. Partners recomputing from Order.amounts may see a ≤$1 difference from FX rounding — the invoice is authoritative.

Document URLs are pinned

Every document_url — on the invoice, on Order.invoice, and inside the webhook — ends in ?version=N for the version that payload describes. A URL you stored from version 1 keeps returning the version-1 PDF after a re-issue. Call the route without version for the current PDF.

GET /v1/invoices — List

Newest created_at first. Same envelope and cursor rules as GET /v1/orders. Drafts are included unless you exclude them with status. Filters combine with AND semantics.

Response — 200 OK

Each entry is the full Invoice resource (abbreviated above).

Errors


GET /v1/invoices/{invoice_id} — Detail

Response — 200 OK

A draft looks the same with status: "draft", number: null, version: 0, document_url: null, issued_at: null, and possibly consignee: null, shipment_month: null, or amounts.price: null while LMN ops are still completing it.

Errors


GET /v1/invoices/{invoice_id}/document — PDF

Streams the “COMMERCIAL INVOICE & PACKING LIST” PDF — Content-Type: application/pdf, Content-Disposition: inline; filename="{number}_v{N}.pdf". This is the only way to obtain the PDF: there are no signed or public URLs, and the route requires your API key like every other. Every published version keeps its own immutable PDF. Sandbox PDFs carry a diagonal SANDBOX — NOT A TAX DOCUMENT watermark. The route counts against the shared /v1 per-key quota like every other call — store the bytes rather than re-downloading per page view.

Errors


GET /v1/orders/{id}/invoice — Invoice for an order

Returns the order’s newest invoice in any status (a draft as soon as the order is secured), same shape as GET /v1/invoices/{invoice_id}. For a quick existence/status check you don’t need this call — read invoice on the order itself.

Errors


Sandbox

Drive a sandbox order to secured with POST /v1/orders/{id}/sandbox-status — LMN drafts the sandbox invoice the same way it does in production, and it shows up on the order and on these routes. Issuing is an LMN-side action in both environments; contact LMN to have a sandbox invoice issued so you can exercise the PDF route and the invoice.issued webhook end-to-end. Sandbox and production invoices are fully separate (numbers, PDFs, webhooks).