Провайдер фулфилмента Packeta (Zásilkovna) для Medusa v2: пункты выдачи, Z-BOX, доставка на дом, оплата при получении, накладные, отслеживание, возвраты
Packeta (Zásilkovna) fulfillment provider for Medusa v2 — pickup points (Z-Point, Z-BOX, external carrier PUDOs), home delivery through Packeta's carrier network across Europe, cash on delivery, labels (PDF/ZPL, Packeta or carrier), push tracking, returns via the claim assistant, plus an admin UI and a storefront widget helper.
Disclaimer: This is an unofficial, community-built integration. It is not affiliated with, endorsed by, or maintained by Packeta s.r.o. / Zásilkovna s.r.o. "Packeta", "Zásilkovna" and their logos are trademarks of their respective owners, used here only to identify the service this plugin integrates with.
npm | Packeta API docs | Medusa Fulfillment Module
bun add medusa-plugin-packeta # or npm / yarn / pnpmThe same options object is passed to the fulfillment provider and to the plugin's module (routes/workflows use the module, the checkout uses the provider). The plugin entry loads the API routes, subscribers, job and admin UI.
1// medusa-config.ts2const packeta = {3 api_password: process.env.PACKETA_API_PASSWORD, // 32-hex API password4 api_key: process.env.PACKETA_API_KEY, // 16-char API key (feeds, widget)5 eshop: process.env.PACKETA_ESHOP, // sender indication (client section → Senders)6 webhook_signing_key: process.env.PACKETA_WEBHOOK_SIGNING_KEY, // from Packeta support, see Push tracking7 // optional — see the table below8 // cod_payment_providers: ["pp_system_default"],9 // enabled_carriers: ["106", "131", "3060"],10 // label_format: "A6 on A6",11}12
13module.exports = defineConfig({14 // ...15 modules: [16 {17 resolve: "@medusajs/medusa/fulfillment",18 options: {19 providers: [20 { resolve: "@medusajs/medusa/fulfillment-manual", id: "manual" },21 { resolve: "medusa-plugin-packeta/providers/packeta", id: "packeta", options: packeta },22 ],23 },24 },25 { resolve: "medusa-plugin-packeta/modules/packeta", options: packeta },26 ],27 plugins: [{ resolve: "medusa-plugin-packeta", options: {} }],28})Then run the plugin's migration (creates the table):
npx medusa db:migrateThe provider is registered as . In the admin: Settings → Locations & Shipping → your location → Fulfillment providers → add Packeta, then create shipping options for the service zone choosing the Packeta fulfillment options (pickup / home delivery / per-carrier). Prices are flat Medusa prices — Packeta has no price API.
| Option | Required | Default | Description |
|---|---|---|---|
| yes | — | REST API password (client section → Support). | |
| yes | — | API key used by the carrier feed, the widget and the widget validate endpoint. | |
| yes | — | Sender indication. Use a dedicated test sender while integrating — Packeta has no sandbox. | |
| no | Payment provider ids that mean cash on delivery. | ||
| no | Packet weight when the order has no variant weights. | ||
| no | Added to the summed variant weights (grams). | ||
| no | , , , , , . | ||
| no | Add one fulfillment option per carrier from the feed. | ||
| no | Carrier ids to expose () or . | ||
| no | Carrier feed cache TTL. | ||
| no | Validate the chosen point through Packeta at checkout. | ||
| no | — | Push-tracking signing key. Without it the webhook answers 503. | |
| no | Accept unsigned webhooks (local development only; ignored in production). | ||
| no | Max age of a webhook timestamp before it is treated as a replay. | ||
| no | / placeholders. | ||
| no | Packeta status ids that mark the fulfillment shipped. | ||
| no | Status ids that mark it delivered. | ||
| no | — | in mm, used when a carrier requires dimensions. | |
| no | — | for non-EU carriers (see Customs). | |
| no | Insured value for return claims when none is passed. | ||
| / / / | no | / / / | Status polling job (fallback for push tracking). |
| , , | no | Packeta production URLs | Overridable for tests. |
1PACKETA_API_PASSWORD=2PACKETA_API_KEY=3PACKETA_ESHOP=4PACKETA_WEBHOOK_SIGNING_KEY=Packeta pickup points are chosen in Packeta's widget on your storefront. Pass the selection as the shipping method ; the provider validates and normalises it.
1import { pickPoint, pickAddress, pointToShippingMethodData, addressToShippingMethodData } from "medusa-plugin-packeta/widget"2
3// Pickup point (Z-Point, Z-BOX, partner PUDO). Filter with `vendors` / `country` if you like.4const point = await pickPoint(process.env.NEXT_PUBLIC_PACKETA_API_KEY!, { language: "cs", country: "cz,sk" })5if (point) {6 await sdk.store.cart.addShippingMethod(cart.id, {7 option_id: pickupShippingOption.id,8 data: pointToShippingMethodData(point),9 })10}11
12// Home delivery: the address from the cart is enough…13await sdk.store.cart.addShippingMethod(cart.id, { option_id: homeShippingOption.id, data: {} })14
15// …or let the customer pick a validated address in Packeta's HD widget (CZ/SK):16const carrierId = (await fetch(`${MEDUSA_URL}/store/packeta/carriers?country=cz`, { headers }).then((r) => r.json())).home_delivery_carrier_id17const address = await pickAddress(process.env.NEXT_PUBLIC_PACKETA_API_KEY!, { carrierId, language: "cs" })18if (address) {19 await sdk.store.cart.addShippingMethod(cart.id, { option_id: homeShippingOption.id, data: addressToShippingMethodData(address, carrierId) })20}The contract (what produces) if you drive the widget yourself:
1// Packeta point2{ "point_id": "79", "point": { "id": "79", "name": "…", "street": "…", "city": "…", "zip": "…", "country": "cz", "group": "zbox", "type": "internal" } }3// Partner carrier point (InPost, PPL, …)4{ "carrier_id": "3060", "carrier_pickup_point_id": "BIA10M", "point": { "name": "…", "type": "external", "carrier_id": "3060", "carrier_pickup_point_id": "BIA10M" } }5// Home delivery with a specific address (optional; the cart address is the default)6{ "address": { "street": "Vinohradská", "house_number": "1", "city": "Praha", "zip": "12000", "country": "cz" } }returns the public carrier list (, , , , , , ) and — handy for widget filters. See for a Next.js starter walkthrough.
| Route | |
|---|---|
| = packet id, barcode or record id | |
| `?type=pdf | |
| → one PDF | |
| pull status from Packeta | |
| cancel at Packeta + Medusa fulfillment | |
| carrier feed () | |
| credentials / feed / webhook status |
Packeta enables webhooks per account: e-mail integrations@packeta.com with your HTTPS URL
https://<your-backend>/hooks/packetaand they issue a signing key → . Requests are verified with in constant time and the timestamp must be within (5 min) of the server clock — unsigned, tampered or replayed requests get 401, unknown packets 200 (so Packeta stops retrying). Events are deduplicated by , and a late/replayed event can never move a delivered / returned / cancelled packet backwards. Until the key is configured, the polling job (every 30 min by default, ) keeps statuses fresh. is for local development only and is ignored when .
COD is applied when the order's payment provider is in (default: Medusa's manual ): is set to at . The admin "Create packet" drawer shows the detected state and lets you override amount/off. Carriers with reject COD packets with a clear error.
Split shipments (several packets per order, from the drawer or native partial fulfillments): the customer pays the order once — the first packet carries the full COD, after which the flag flips to (with ) and every later packet is created with COD 0 unless you pass explicitly. Each packet is insured for the value of the items it carries (plus shipping on the first one) and follow-up packets get a , reference.
For carriers flagged in the feed the plugin sends (ead, deliveryCost, invoiceNumber, invoiceIssueDate) and built from the order lines (variant/product , , title, value, units, weight). Configure ( default), fallbacks (, ) and pass per-packet extras (, , , ) via when creating the fulfillment programmatically. See Packeta's customs documentation.
1bun install2bun run check # format + lint + typecheck + unit tests3bun run build # medusa plugin:build → .medusa/server4bun run test:integration # boots a real Medusa app against a mocked Packeta API (needs Postgres: DB_HOST/DB_PORT/DB_USERNAME/DB_PASSWORD)Live smoke against your Packeta account (creates and cancels a real, free packet — use a test sender):
1PACKETA_API_PASSWORD=… PACKETA_API_KEY=… PACKETA_ESHOP=… bun run smoke2bun run smoke carriers cz # feed3bun run smoke validate 79 # widget validate endpoint4bun run smoke label <packetId> # write label PDFTry it inside a Medusa app without publishing: builds, packs and installs the tarball, then follow the config above.
MIT
This project is an independent, unofficial integration and is not affiliated with or endorsed by Packeta s.r.o. / Zásilkovna s.r.o. All Packeta and Zásilkovna trademarks and logos are the property of their respective owners.