MeyktAPI Documentation
OpenAPI specllms-full.txtDashboard
  • Overview
  • Quickstart
  • Authentication
  • Orders
  • Customers
  • Files
  • Webhooks
  • Articles & variants
  • Goods conditions
  • Sets & stock structures
  • Manufacturing
  • Inbound deliveries
  • Returns
  • Inventory
  • Shipping
  • Integration profiles
  • Errors

Shipping and progress

Read actual order progress and shipment proof through your own API connection. The source-order reads require orders:read. They accept the Meykt order ID returned by order creation. They do not accept another organization's ID as an access credential.

#Current progress

GET /v1/orders/{id}/progress — requires orders:read.

bash
curl 'https://api.meykt.com/v1/orders/8c4d2f9a-5b71-4e6c-9a03-1f7d8e2b6c45/progress' \
  -H "Authorization: Bearer $MEYKT_API_KEY"
json
{
  "data": {
    "order_id": "8c4d2f9a-5b71-4e6c-9a03-1f7d8e2b6c45",
    "picking": "started",
    "production": "not_required",
    "shipping": "not_started",
    "attention": [],
    "historical_work_started": true,
    "observed_at": "2026-10-18T20:00:00Z"
  }
}

Picking and production are separate dimensions. Their values are not_required, not_started, started, completed, failed or unknown as applicable. not_required requires an explicit applicable instruction, such as an order configured for warehouse shipping without production. Missing instructions or insufficient evidence produce unknown; do not treat it as completed or as permission to edit.

Shipping is not_started, partial, completed or unknown. partial means that actual shipments cover some current source quantities; several partners may fulfill different parts of the source order. completed requires proof for every current source quantity. A manual shipping status without matching physical proof is unknown.

attention can include query, paused, on_hold, failed, needs_review and change_pending. These are categories, not internal partner records. Read the latest order revision and the durable change/cancellation result before attempting a write. Progress is a read, never authorization to bypass a work-start fence.

Changes require orders:change; cancellation requires orders:cancel. Give each operation its explicit scope. The existing orders:write scope permits creation.

historical_work_started retains recorded work evidence even after jobs have been reset. For example, production can currently be not_started while historical work remains true. Resetting a display status does not make previously processed goods untouched. Silent internal repeat runs do not replace ordinary current production progress.

#Actual shipments

GET /v1/orders/{id}/shipments — requires orders:read.

bash
curl 'https://api.meykt.com/v1/orders/8c4d2f9a-5b71-4e6c-9a03-1f7d8e2b6c45/shipments' \
  -H "Authorization: Bearer $MEYKT_API_KEY"
json
{
  "data": {
    "order_id": "8c4d2f9a-5b71-4e6c-9a03-1f7d8e2b6c45",
    "observed_at": "2026-10-18T20:00:00Z",
    "complete": true,
    "shipments": [{
      "id": "2e24952c-7b63-4eea-8d3f-9149013310c2",
      "shipped_at": "2026-10-18T19:55:00Z",
      "lines": [{
        "order_item_id": "f6de003e-a0a7-4ac2-82dd-8a941836456b",
        "external_line_id": "ERP-LINE-1",
        "quantity": "2"
      }],
      "packages": [
        { "id": "0735f5cf-7f36-44f4-8cc7-e1de8071bfdb", "number": 1, "tracking": [{ "carrier": "dhl", "number": "123456789012" }] },
        { "id": "6e08136b-4f14-4839-9640-ce7da210482c", "number": 2, "tracking": [{ "carrier": "dhl", "number": "123456789013" }] }
      ]
    }]
  }
}
  • Shipment and package IDs are stable opaque references in your authorized view.
  • order_item_id refers to your source order, including when a partner or its subcontractor performed the work. external_line_id carries your supplied line reference when available.
  • quantity is an exact decimal string. Identical SKUs on different personalized lines remain separate.
  • packages lists all packages in that completed packing. A package identity does not prove its individual item contents; the API does not repeat every shipment line as the contents of every package.
  • shipped_at records actual physical handover. Buying or printing a label does not create shipment proof.
  • Tracking comes from proven issued labels or explicitly recorded carrier-neutral tracking. Sandbox and cancelled labels are excluded. tracking: [] means no supported recorded tracking is available; an external/manual label is not guessed from another field.

This compatibility response includes proven whole-order and independent partial dispatches while retaining its original shape. Use /orders/{id}/dispatches for exact package contents, remaining quantities and cancellation decisions. complete requires all ordered quantities to have shipped; a cancelled remainder does not count as shipped.

Separate component shipments that do not yet fulfill a whole parent cannot fit this scalar compatibility response. It returns 409 operation_state_conflict with a link to the component-aware dispatch path above; retrying the old read does not solve that representation limit. The detailed dispatch read retains every real component shipment without inventing parent quantities.

The response is bounded to 100 shipments, 250 source lines per shipment, 100 packages per shipment and 10 tracking entries per package. It has no pagination: an unavailable or oversized proof is an error, not a truncated success. Keep a previous confirmed result and retry a failed read; do not infer cancellation, zero shipped quantity or absent tracking from a transport failure.

#Partner scope and generations

You read the customer projection using your own organization and API key. You never need the fulfiller's key. Current active partner relationships and the applicable transfer generations determine the projection. Old replaced copies, a single production cancellation or one partner's completion do not imply cancellation or completion of your entire order.

A known order belonging to another API connection or key environment returns the same 404 not_found as an unknown order. Test keys cannot read live shipment/progress data. They only address orders created in the test environment; test orders create no physical warehouse shipments.

#Receiving shipping events

order.received confirms that the order and every accepted line committed together. Product matching and compilation can continue afterward; receipt does not confirm that warehouse work has started.

order.shipped announces actual shipment proof through the existing signed webhook channel. Its data includes order_id, external_order_id, the source-authorized shipments and source complete. Store event IDs for deduplication and reload this endpoint to reconcile current generations. See Webhooks.

A delayed message is rechecked before delivery. A revoked sharing scope or replaced generation can prevent delivery; temporary projection failure is retried. Use the progress read to reconcile current evidence. New dispatch-domain events require explicit subscriptions; existing webhook subscriptions do not silently receive them.

These endpoints do not update Shopify, book incoming deliveries or process returns. Those are separate business capabilities, not side effects of reading status.

#Source quantities and package contents

GET /v1/orders/{id}/dispatches requires orders:read. It returns your source order across its authorized fulfillment chain. Use your own key, never the fulfiller's key. Source reads, cancellations and receipts also check the key creator's current order-view/edit rights; a retained scope cannot override a removed membership or a downgraded role. revision is a freshness fingerprint for quantity changes; it is not a timestamp or an access credential.

Each source line has exact decimal strings ordered, allocated, shipped, cancelled, remaining and unallocated. Remaining is ordered minus shipped minus cancelled; allocated quantities are included in remaining. Physically bound quantities need warehouse recovery before cancellation.

complete means everything shipped. closed means everything shipped or was explicitly cancelled. The separate closure.state describes whether ordinary operational/billing closure still needs review. For 5 ordered → 2 shipped → 1 cancelled → 2 shipped, the final values are shipped4, cancelled1, remaining0, closed=true and complete=false. Cancelling demand does not create a credit.

Packages have proven contents with source-line quantities. Never repeat every shipment line in every package. Legacy packages lacking individual content proof retain that distinction. Stable opaque shipment/package references support reconciliation and returns; they are not warehouse access credentials.

Virtual sets also expose immutable component references and actual component quantities. Adding component quantities does not give fulfilled parent sets. A component-only shipment can have parent quantity: "0" and positive component quantities; complete component evidence advances parent fulfillment. Store the component reference and source-line ID, not just the SKU. Physical kits are separate stock articles.

The detailed read is bounded to 250 shipments/sections and 200 source lines, with at most 100 packages per shipment. Oversized or unavailable proof fails explicitly; failed reads never imply missing shipments or cancelled quantities.

#Cancel a selected remainder

POST /v1/orders/{id}/remaining-cancellations requires orders:cancel_remaining. Read the current dispatch revision first:

json
{
  "request_id": "e9b5af11-c6cf-4baf-9964-85ea3b55a031",
  "expected_revision": "5b7a9431e1ab09e40b248dc9acdf76a03f4de9574ead08a2b3b107f02e5d1a66",
  "reason": "The customer needs one unit fewer.",
  "lines": [{
    "order_item_id": "f6de003e-a0a7-4ac2-82dd-8a941836456b",
    "quantity": "1"
  }]
}

The receipt contains command_id, order_id, request_id, state, lines, code and billing_changed: false. completed confirms accepted cancellation. decision_required means a partner must decide; it is not a cancellation. The endpoint cannot release another business's stock or silently change charges.

Persist the original request and UUID. Repeating POST returns its original immutable receipt even after a partner answers. Read GET /v1/orders/{id}/remaining-cancellations/{requestId} with orders:read for the current completed, decision_required or rejected decision. The UI, HTTP and AI tools retain the same original API-order idempotency context. Changing the body under the same UUID is a conflict.

#Operate your own warehouse

Operator endpoints resolve the current API-key creator. They recheck the key, active connection, current membership, warehouse rights and applicable partner grants. A customer's key is not authority to operate the fulfiller's warehouse. Test keys cannot inspect or mutate live warehouse, production or billing data; use isolated simulator fixtures for physical tests.

Method and pathScopePurpose
GET /v1/dispatches?order_id=…dispatch:readSections, versions and operational quantities
GET /v1/dispatches/options?order_id=…dispatch:readNamed warehouses, lines, components and arrival claims
GET /v1/dispatches/boxes?warehouse_id=…dispatch:readBox choices; optional search, limit and offset
POST /v1/dispatches/commands/previewdispatch:read, dispatch:writeCheck the real command, then roll it back
POST /v1/dispatches/commandsdispatch:writeExecute one versioned section command
GET /v1/dispatches/commands/{idempotencyKey}dispatch:readRecover this connection's original receipt

Select IDs from the named options. The order must first be admitted to its warehouse fulfillment process. Existing whole-order work cannot silently become a partial section after it starts. Resolve that work before planning sections. Each section reserves only its selected quantities. Other sections may progress independently under the same source-demand limit.

Every command has idempotency_key, operation and optional recovery_only. Generate one new section UUID and one command UUID for a plan and persist both:

json
{
  "idempotency_key": "2c6ce039-01a9-41b9-b041-22150e7dbe24",
  "operation": {
    "kind": "plan",
    "section_id": "ac4b84da-7ffc-4a5e-8187-2c46fc26bbd1",
    "order_id": "8c4d2f9a-5b71-4e6c-9a03-1f7d8e2b6c45",
    "warehouse_id": "3fcc3106-d40e-447b-88b8-31452cecfc82",
    "lines": [{
      "order_item_id": "f6de003e-a0a7-4ac2-82dd-8a941836456b",
      "quantity": "2",
      "received_claim_ids": []
    }]
  }
}

The receipt includes the resulting section and version. Use that version for the next command. Preview returns {saved:false, preview:{…}} and leaves no reservation, job or receipt. It is a feasibility check, not a future reservation.

All operations after plan use section_id and expected_version:

OperationFurther fieldsEffect
plansection_id, order_id, warehouse_id, linesReserve selected quantities
reviselinesReplace an untouched plan
pickbox_id, physically_confirmed:trueConfirm actual stock movement into a box
packpackages, physically_confirmed:trueRecord exact physical package contents
confirmphysically_confirmed:trueConfirm handover and book goods issue
unpackreason, physically_confirmed:trueRecover unshipped packed goods
return_rawreason, physically_confirmed:trueReturn eligible unprocessed picked stock
cancel_sectionreasonRelease an untouched section allocation
tracking_recordpackage_id, carrier, numberRecord real carrier tracking
tracking_correctpackage_id, carrier, number, previous_tracking_id, reasonCorrect one tracking entry with history

Current package/dispatch reads return all currently recorded tracking entries, with replaced manual entries omitted. Multiple returned entries remain current together; recorded_at and list order do not imply replacement. tracking_record adds an entry. tracking_correct replaces only the current previous_tracking_id on that same package, with a required reason; it does not replace the package's other tracking entries. Use the ID from the operator's current dispatch read, not an owner shipment projection. A stale or already replaced reference is a conflict: reread before preparing another correction.

The current tracking array is not a replacement-history feed. An immutable command receipt retains its original result, so reread the current package after recovering a receipt. For example, recording A and then B yields both A and B; correcting A to C yields B and C. Recording tracking does not validate the number with a carrier, cancel an issued label or book another physical shipment.

cancel_section releases allocation; it does not cancel source demand. Processed goods cannot become untouched through a status edit. Physical confirmation means the real-world action occurred; do not infer it from planning or buying a label.

packages contains consecutive number values starting at 1 and contents entries with section_line_id, quantity and optional component_id. These are section IDs from the receipt, not source-line IDs. All packages together must exactly cover the selected physical quantities. Two packages may split a line. For a parent with multiple components, component_id is required and quantity means actual component units.

For complete sets, provide the parent lines[].quantity without components. For separate component shipments, use lines[].components:[{component_ref,quantity,received_claim_ids}] from options. Use component remaining quantities: a parent can have no unallocated whole sets while a missing component is still free. The commercial parent quantity equals the ceiling of the largest selected component quantity divided by its per-parent factor. Meykt validates this exactly and preserves frozen component identity and condition policy.

Converted arrival claims already reserve real stock. Select their advertised received_claim_ids to transfer existing holds instead of reserving twice. Open expected arrivals and held receipts must finish their receiving/release steps before ordinary allocation.

#Production and final closure

Method and pathScopePurpose
GET /v1/dispatches/production-options?section_id=…dispatch:productionExact production quantities and workflow choices
POST /v1/dispatches/production-commands/previewdispatch:productionValidate preparation without saving jobs
POST /v1/dispatches/production-commandsdispatch:productionCreate pending section jobs
GET /v1/dispatches/production-commands/{idempotencyKey}dispatch:productionRecover the actual job receipt
GET /v1/dispatches/closure?order_id=…dispatch:closeRead work and closure prerequisites
POST /v1/dispatches/closure/previewdispatch:closeRead billing review for {order_id}
POST /v1/dispatches/closuredispatch:closeComplete through the normal reviewed billing path
GET /v1/dispatches/closure/commands/{idempotencyKey}dispatch:closeRecover the original final receipt

Production preparation takes idempotency_key, section_id, expected_version, priority (low/normal/high/urgent, default normal), and workflows:[{line_id,workflow_id,component_id?}]. Select one workflow for each offered production component; include component_id for multiple components. Pending jobs do not start machines. Central controls runtime; packing waits for actual quantity-bound completion and required follow-up work. The creator needs current production-creation rights; a scope alone does not grant them.

Closure requires current order/fulfillment-management rights. Preview returns {closure,billing} with actual positions/totals and preview_token. Send {idempotency_key,order_id,billing_choice,preview_token} after explicitly choosing preserve or reverse. After any shipment, preserve charges; later credits remain a separate reviewed action. A stale preview fails instead of applying a changed financial decision. Quantity closure and operational/billing closure are separate.

#Recover an uncertain result

Persist exact commands before sending. After a timeout or 503 command_outcome_unknown, retrieve the receipt or repeat the same body and UUID. data:null means no accessible confirmed receipt; it does not prove that nothing happened. Do not start over with a new UUID. On ordinary section commands, recovery_only:true permits recovery without a fresh booking. Production and closure receipts also remain bound to the originating connection.

An unavailable API entitlement or revoked access does not prove that an earlier request had no effect. The existing connection entitlement still applies; use a currently authorized UI, shared AI tool or data export to reconcile the result. Keep the original request and business idempotency key. Do not create a new booking merely because the API cannot currently return its receipt.

409 resource_revision_conflict needs a fresh read and newly reviewed command. 409 idempotency_conflict needs the original request, not an invented new UUID. 422 validation_failed lists invalid fields. 403 indicates missing authority; 404 does not distinguish unknown from foreign targets. Keep confirmed state when a temporary read fails.

New dispatch events are explicitly opt-in through the shared signed webhook channel. Deduplicate event IDs and reload the source view. Delivery is retryable, not ordered exactly once; current grants are checked again before delivery. Use reads for initial synchronization and periodic reconciliation. See Webhooks for subscriptions, signatures and retries.

Machine-readable version of this page: https://www.meykt.com/developers/shipping.md

On this page

  • Current progress
  • Actual shipments
  • Partner scope and generations
  • Receiving shipping events
  • Source quantities and package contents
  • Cancel a selected remainder
  • Operate your own warehouse
  • Production and final closure
  • Recover an uncertain result

Base URL https://api.meykt.com/v1 · Machine-readable: openapi.json · llms-full.txt

Imprint · Privacy · Terms