InPost
Add InPost parcel locker and courier delivery
medusa-inpost-fulfillment
InPost fulfillment provider plugin for MedusaJS v2. Integrates with the InPost ShipX API to support Paczkomat locker and courier delivery.
π§ͺ Beta testers wanted
This plugin has been tested thoroughly against the InPost sandbox, but not yet end-to-end against a production InPost account. If you have production InPost ShipX credentials and are using Medusa v2, I'd love your help validating real locker and courier shipments.
What you'd get:
Reach out by opening a GitHub issue or emailing the maintainer. Bug reports from production use are especially welcome.
- Free setup assistance
- Priority bug fixes
Features
- Paczkomat locker delivery (Copy to clipboard
inpost_locker_standard) β ships to a selected InPost locker machine - Courier delivery (Copy to clipboard
inpost_courier_standard) β ships to the receiver's address with automatic dispatch order creation - Automatic offer selection and purchase (for prepaid accounts)
- Local InPost shipment history stored in Medusa
- Admin API for shipment list, details, status refresh, labels, and cancellation
- Scheduled status synchronization for active shipments
- Shipment label retrieval (PDF/ZPL)
- Shipment cancellation
- Polish postal code normalization (5 digits to XX-XXX format)
- Parcel dimensions aggregated from cart item variants
Prerequisites
- MedusaJS v2 (Copy to clipboard
@medusajs/framework^2.5.0) - Node.js >= 20
- InPost ShipX API credentials (register here)
InPost API version
This plugin currently integrates with the Polish InPost ShipX v1 API:
- Sandbox: Copy to clipboard
https://sandbox-api-shipx-pl.easypack24.net/v1 - Production: Copy to clipboard
https://api-shipx-pl.easypack24.net/v1
It does not yet use the newer InPost Global API (Copy to clipboard/shipping/v2 on Copy to clipboardapi.inpost-group.com). Migrating to the Global API requires separate changes to authentication, shipment payloads, label retrieval, tracking identifiers, and endpoint URLs.
Installation
1npm install medusa-inpost-fulfillment
After installing or upgrading to a version that includes the InPost shipment module, run Medusa migrations:
1npx medusa db:migrate
Configuration
Add the plugin to your Copy to clipboardmedusa-config.ts:
1234567891011121314151617181920import { defineConfig } from "@medusajs/framework/utils";const inpostOptions = {// RequiredapiToken: process.env.INPOST_API_TOKEN,organizationId: process.env.INPOST_ORGANIZATION_ID,// Optional β use InPost sandbox environment (default: false)sandbox: true,// Optional β default parcel template for locker shipments// "small" | "medium" | "large" (default: "small")defaultParcelTemplate: "small",// Optional β default shipment label format// "pdf" | "zpl" (default: "pdf")defaultLabelFormat: "pdf",// Required for courier shipments β sender detailssender: {
The Copy to clipboardmedusa-inpost-fulfillment plugin registration must be placed in Copy to clipboardplugins. It lets Medusa discover the plugin's Copy to clipboardinpost module, Admin API routes, scheduled jobs, and migrations. Do not place Copy to clipboardresolve: "medusa-inpost-fulfillment" in Copy to clipboardmodules.
The fulfillment provider registration under Copy to clipboard@medusajs/medusa/fulfillment must stay in Copy to clipboardmodules, because it tells Medusa's fulfillment module that InPost is available as a shipping provider.
Environment variables
Variable Description Copy to clipboardINPOST_API_TOKEN Your InPost ShipX API token Copy to clipboardINPOST_ORGANIZATION_ID Your InPost organization ID
Shipping options
After installing the plugin, create shipping options in the Medusa admin that use the InPost fulfillment provider. The plugin exposes two services:
Service ID Description Copy to clipboardinpost_locker_standard Paczkomat locker delivery Copy to clipboardinpost_courier_standard Courier home delivery
Where to find your shipments
InPost uses different apps for locker and courier shipments:
- Locker (Paczkomat) shipments β visible in Manager Paczek (sandbox: sandbox-manager.paczkomaty.pl)
- Courier shipments β visible in WebTrucker at kurier.inpost.pl under "PrzesyΕki do nadania" (Shipments to send), and later under "Monitoring" once InPost processes them
Note on sandbox for courier shipments: WebTrucker has no sandbox equivalent, so courier shipments created in sandbox will not appear in any UI. In sandbox, a correctly created courier shipment will simply reach status Copy to clipboardconfirmed via the API β that is the sandbox success criterion. Only production courier shipments are visible in WebTrucker.Storefront integration
Locker delivery
For Paczkomat locker delivery, the storefront must pass Copy to clipboardtarget_point (the Paczkomat machine ID) when adding a shipping method to the cart:
123456await sdk.store.cart.addShippingMethod(cartId, {option_id: lockerShippingOptionId,data: {target_point: "WAW123", // Paczkomat machine ID},});
You can use the InPost Geowidget to let customers pick a Paczkomat on a map.
Courier delivery
For courier delivery, no additional data is needed β the receiver address is taken from the cart's shipping address:
123await sdk.store.cart.addShippingMethod(cartId, {option_id: courierShippingOptionId,});
Address requirements
InPost ShipX expects the street and building number as separate address fields. The storefront checkout should collect and save them separately:
Storefront field Medusa shipping address field Required First name Copy to clipboardshipping_address.first_name Yes Last name Copy to clipboardshipping_address.last_name Yes Street Copy to clipboardshipping_address.address_1 Yes Building number Copy to clipboardshipping_address.address_2 Yes Postal code Copy to clipboardshipping_address.postal_code Yes City Copy to clipboardshipping_address.city Yes Country Copy to clipboardshipping_address.country_code Yes Phone Copy to clipboardshipping_address.phone Yes Company Copy to clipboardshipping_address.company No State / province Copy to clipboardshipping_address.province No Apartment / flat number Copy to clipboardshipping_address.metadata.flat_number No
Do not put the full street address with building number into Copy to clipboardaddress_1 (for example Copy to clipboardMarszalkowska 10). Use Copy to clipboardaddress_1 for the street name only and Copy to clipboardaddress_2 for the building number.
If the storefront has a single Copy to clipboardAddress field, split it into separate Copy to clipboardStreet and Copy to clipboardBuilding number inputs before using this provider.
Parcel dimensions
For courier shipments, the plugin aggregates parcel dimensions from cart item variants (the Copy to clipboardweight, Copy to clipboardlength, Copy to clipboardheight, and Copy to clipboardwidth fields on product variants). If no dimensions are available, Copy to clipboardparcel_dimensions must be provided in fulfillment data. The plugin does not silently fall back to placeholder parcel dimensions.
For locker shipments, a parcel template (Copy to clipboardsmall, Copy to clipboardmedium, or Copy to clipboardlarge) is used instead, configurable via the Copy to clipboarddefaultParcelTemplate option or per-shipment via Copy to clipboardparcel_template in fulfillment data.
InPost shipment history
The plugin includes an Copy to clipboardinpost module that stores a local record after a ShipX shipment is created successfully. This makes shipment data available outside of Copy to clipboardfulfillment.data and gives the admin API a stable source for list/detail views and status synchronization.
Local shipment history is recorded asynchronously: after Medusa creates an order fulfillment, the plugin listens to the Copy to clipboardorder.fulfillment_created event, reads the InPost shipment data from Copy to clipboardfulfillment.data, and upserts an Copy to clipboardInpostShipment record.
Stored fields include:
- Copy to clipboard
order_id - Copy to clipboard
fulfillment_id - Copy to clipboard
shipment_id - Copy to clipboard
tracking_number - Copy to clipboard
service_type - Copy to clipboard
status - Copy to clipboard
label_format - Copy to clipboard
dispatch_order_id - Copy to clipboard
last_synced_at - Copy to clipboard
last_error - Copy to clipboard
raw_response
Admin API
The following admin routes are available:
Method Path Description Copy to clipboardGET Copy to clipboard/admin/inpost/shipments List local InPost shipments Copy to clipboardGET Copy to clipboard/admin/inpost/shipments/:id Retrieve one local shipment Copy to clipboardPOST Copy to clipboard/admin/inpost/shipments/:id/refresh Refresh shipment data from ShipX Copy to clipboardGET Copy to clipboard/admin/inpost/shipments/:id/label Download shipment label Copy to clipboardDELETE Copy to clipboard/admin/inpost/shipments/:id Cancel shipment in ShipX if allowed
List filters: Copy to clipboardorder_id, Copy to clipboardfulfillment_id, Copy to clipboardshipment_id, Copy to clipboardtracking_number, Copy to clipboardq, Copy to clipboardstatus, Copy to clipboardservice_type, Copy to clipboardstate, Copy to clipboarderrors, Copy to clipboarddate_from, Copy to clipboarddate_to, Copy to clipboardlimit, and Copy to clipboardoffset.
Supported list filter values:
Query param Description Copy to clipboardq Searches order ID, fulfillment ID, shipment ID, tracking number, and dispatch order ID Copy to clipboardservice_type Copy to clipboardinpost_locker_standard or Copy to clipboardinpost_courier_standard Copy to clipboardstate Copy to clipboardactive or Copy to clipboardcanceled Copy to clipboarderrors Copy to clipboardwith or Copy to clipboardwithout Copy to clipboarddate_from Shipment creation date lower bound, Copy to clipboardYYYY-MM-DD Copy to clipboarddate_to Shipment creation date upper bound, Copy to clipboardYYYY-MM-DD
Label download accepts an optional Copy to clipboardformat query parameter:
12/admin/inpost/shipments/:id/label?format=pdf/admin/inpost/shipments/:id/label?format=zpl
Active shipments are synchronized every 15 minutes by the Copy to clipboardsync-inpost-shipments scheduled job.
Admin UI
The plugin adds an Admin UI extension under InPost. The shipments view uses the plugin Admin API and lets store staff:
- browse locally recorded InPost shipments,
- search by order ID, fulfillment ID, ShipX shipment ID, tracking number, receiver, or destination,
- filter by status, service type, and sync errors,
- refresh shipment data from ShipX,
- download PDF or ZPL labels,
- open public InPost tracking,
- copy the tracking number,
- cancel cancellable shipments,
- inspect the raw ShipX response.
The plugin also adds an order details widget showing InPost shipments recorded for the current order.
How it works
Fulfillment flow
- Create shipment β sends parcel, receiver, and sender data to InPost ShipX API
- Offer handling β for prepaid accounts, the plugin polls for offers, selects the first available one, and purchases it
- Dispatch order (courier only) β creates a dispatch order to schedule courier pickup from the sender's address
- Return data β stores Copy to clipboard
shipment_id, Copy to clipboardtracking_number, and Copy to clipboarddispatch_order_idin the fulfillment data - Local history β after Medusa emits Copy to clipboard
order.fulfillment_created, the plugin upserts an Copy to clipboardInpostShipmentrecord in the Copy to clipboardinpostmodule
Cancellation
When a fulfillment is cancelled in Medusa, the plugin attempts to cancel the corresponding shipment in InPost.
ShipX cancellation is only possible before the shipment is confirmed. The plugin treats the following statuses as cancellable through the API:
- Copy to clipboard
created - Copy to clipboard
offers_prepared - Copy to clipboard
offer_selected
Once a shipment reaches Copy to clipboardconfirmed, ShipX rejects cancellation with Copy to clipboardinvalid_action. In that case, the plugin does not call the cancellation endpoint and lets Medusa cancel the fulfillment locally only. The physical shipment must then be cancelled manually in InPost Manager for locker shipments or WebTrucker for courier shipments.
The Admin UI disables the Cancel shipment action for non-cancellable statuses and shows a tooltip explaining that the shipment must be cancelled manually in InPost.
See the official InPost ShipX cancellation docs: Anulowanie przesyΕki.
Labels
The plugin supports retrieving shipment labels as PDF documents through Medusa's fulfillment documents API.
Returns
Return shipments are not created automatically β they should be created manually in InPost Manager, as Medusa's return flow does not provide sufficient data (e.g., target locker for locker returns).
Options reference
Option Type Required Default Description Copy to clipboardapiToken Copy to clipboardstring Yes β InPost ShipX API token Copy to clipboardorganizationId Copy to clipboardstring Yes β InPost organization ID Copy to clipboardsandbox Copy to clipboardboolean No Copy to clipboardfalse Use sandbox API environment Copy to clipboarddefaultParcelTemplate Copy to clipboard"small" | "medium" | "large" No Copy to clipboard"small" Default parcel template for locker shipments Copy to clipboarddefaultLabelFormat Copy to clipboard"pdf" | "zpl" No Copy to clipboard"pdf" Default label format for shipment documents Copy to clipboardsender Copy to clipboardobject For courier β Sender details (required for courier shipments) Copy to clipboardsender.company_name Copy to clipboardstring For courier β Sender company name Copy to clipboardsender.first_name Copy to clipboardstring For courier β Sender first name Copy to clipboardsender.last_name Copy to clipboardstring For courier β Sender last name Copy to clipboardsender.email Copy to clipboardstring Yes β Sender email Copy to clipboardsender.phone Copy to clipboardstring Yes β Sender phone number Copy to clipboardsender.address Copy to clipboardobject Yes β Sender address
License
MIT

