Dpd
Work in progress: DPD by Koda Plus, the DPD Polska courier and DPD Pickup points for Medusa, with cash on delivery. This version creates DPD courier shipments within Poland and DPD Pickup shipments to points in Poland, with or without cash on delivery, fr
DPD by Koda Plus
Ship with DPD Polska from Medusa: the DPD courier and DPD Pickup points, both also with cash on delivery, on the DPD Polska web services.
A fulfillment provider with five shipping options checks the chosen DPD Pickup point at checkout and records it on the fulfillment. The plugin turns that fulfillment into a DPD shipment from a plan a person reads first, stores the label, hands the parcels over to the DPD courier with a protocol, follows the statuses in the DPD InfoServices and, if you want, marks the fulfillments shipped and delivered in Medusa.
Writes are off by default. Without them the plugin already works: fulfillments record the option and the point, plans show exactly what would be sent. Creating shipments, ordering the courier and writing statuses to Medusa happen only when you allow the writer in the options and arm it in the admin.
Scope of this version. Courier and DPD Pickup shipments within Poland, with or without cash on delivery, labels, the handover to the courier (the protocol and the courier order) and statuses. Returns, shipments abroad, the queue mode of the DPD InfoServices and the DPD tracking link in the Medusa label come in the next versions; until then the plan of a return or of a shipment abroad says so and nothing is sent to DPD.

Live demo: Medusa admin medusa.koda.plus/app/dpd, signed in to a public demo account by the link itself, and the storefront demo.koda.plus with DPD courier and DPD Pickup at checkout. The demo runs on the DPD sandbox: waybills and test labels come from DPD's demo host, and the statuses are simulated, because DPD has no test host for the InfoServices.
What it does
- Checkout: five fulfillment options, , , , and (the return option, used only for returns, claims and exchanges). A courier option needs a complete address in a country of the store; a Pickup option needs a point id of the right shape and a phone or an e-mail of the recipient; cash on delivery needs a currency the options allow for the destination.
- Fulfillment: creating a fulfillment records the option and the choice of the customer, and builds its plan. With and the shipment writer armed, a plan without problems is sent to DPD at once; otherwise the shipment waits for a person.
- Courier shipments in Poland (, ): a person opens the plan of a fulfillment, reads the receiver (read from the order at that moment), the sender, the boxes, the cash on delivery and the exact request to DPD, and confirms it. One click creates the shipment in DPD () and gets its label (). The create carries the hash of the plan that was read: when the order, the settings or the boxes changed since, it is refused and the new plan is shown. A plan with problems sends nothing.
- DPD Pickup shipments in Poland (, ): the checkout checks the point the customer chose and keeps a public snapshot of it (name, address, kind of point) with the shipping method. The plan reads the point again, fresh, and sends it as the of the service, with the cash on delivery next to it for ; the person who collects is read from the order and needs a phone or an e-mail. DPD takes one box of at most 20 kg (20 kg itself goes). When the point was confirmed and the box has all three sides, the box is also checked against the size limits of its kind of point (a locker and a Żabka take smaller boxes). A point that is inactive, hands out no parcels, takes no cash on delivery for a shipment or lies outside Poland is a problem of the plan, and nothing is sent.
- Boxes: by default one box with the weight of the variants (), or when the variants have no weight. The plan can set 1 to 100 boxes by hand, each with its weight and sides, and go back to the automatic ones.
- Cash on delivery: the amount is what is still due (the order total minus the captured payments), sent with two decimals, in a currency allows. One shipment of the order carries it; further shipments of the same order go without it. An order paid online () gets no cash on delivery at all.
- Labels: A4 or , chosen when creating the shipment (the default is ). The label PDF is stored with the shipment and served from the database, so opening it again never asks DPD again. A shipment created without its label (a timeout, an error of DPD) keeps its waybills and the label can be asked for again. Stored labels are removed after .
- Unclear answers: a create that gets no clear answer from DPD (a timeout, a network error, a 5xx, an answer that does not parse) is never sent again blindly. The shipment goes to , and two minutes later it is looked up in DPD by its reference, either by the shipment pass or by the Check in DPD button. Found, its waybills and label are taken over; not found, it goes back to waiting and can be created again with the same reference. When what DPD has does not match what was sent (another number of waybills), the shipment is and a person accepts DPD's waybills or marks it as handled outside the plugin.
- Handover to the courier: a person selects labeled shipments of one sender and gets one DPD protocol for them; then, optionally, orders the DPD courier for that handover. See Handover to the courier below.
- Statuses: a job of its own asks the DPD InfoServices every 5 minutes about each waybill of a shipment after the handover (less often before it). The admin shows the stage of the shipment, the last DPD description and the waybills with their stages; see Statuses below.
- Medusa follows DPD (optional, the writer): the fulfillment is marked shipped when DPD has the parcel in its hands, and delivered when every waybill is delivered. The waybill goes into the labels of the fulfillment.
- The shipment pass, every 5 minutes: removes old labels, takes back claims that ran out, looks up unclear shipments and, with , creates the new shipments and asks again for labels that did not come. It never takes a backlog: only fulfillments recorded after the writer was armed and within . It also takes back the claims of handovers that ran out, but it never prints a protocol and never orders a courier. Statuses run in their own job, so missing DPDServices credentials or a writer that is not armed never stop them.
- Admin page under DPD in the sidebar, with the shipment lists and their actions, the plan drawer, Settings and the writers, and an order card with the shipments of the order and their actions. Each shipment shows its stage, the DPD description and its waybills with their stages, with "Refresh the status" and "Write the status to Medusa again".
- Demo mode (): the same code paths with a simulated DPD. Sample shipments are built from the store's own orders, labels and protocols are sample PDFs, the courier order and the statuses are simulated, and the status writer writes only the history; nothing is sent to DPD.
DPD Pickup
Where the points come from. Live, from DPD's MyPudo API, with and (HTTP Basic) or ; the login and password win when both are set. In the sandbox, from a small test catalog, because MyPudo has no test host: is the only point that passes (the DPD demo host accepts no other), and (inactive) and (no parcels handed out) are there to be refused. In demo mode, from a sample catalog, to (a DPD point, a locker, a Żabka, a kiosk and a shop), plus (inactive) and (send only), which the search never shows. The sandbox and demo mode never call MyPudo. The admin Settings say how points are checked; a live store without MyPudo credentials gets a note there, because every point is then accepted unchecked.
The checkout checks the point fresh, within . A confirmed point passes with its snapshot. A point that is not there, inactive, handing out no parcels, without cash on delivery for a cash on delivery option, or outside Poland, is refused with a message for the customer. When the point cannot be checked (no MyPudo credentials, a timeout, a network error, an error status, an answer that does not parse, an error of MyPudo, a wrong key included), the checkout lets the point through without a check and logs a warning, so a MyPudo outage never stops the sales of DPD Pickup; an id outside Poland is refused even then. DPD still refuses a wrong point when the shipment is created, and the plan shows a warning for a point it could not check. In demo mode a point id of the right shape that is not in the sample catalog is accepted at the checkout without a check (a demo store may use real ids, from the PudoFinder widget); its plan then shows the point as not found, and the admin can change it.
autoCreate never sends a DPD Pickup shipment to a point nobody could check. Such a shipment stays pending, the shipment pass tries it again within , and after that it waits for a person. A person who reads the plan with its warning can still create it by hand.
Changing the point. The plan drawer of a pending or failed Pickup shipment has a point search and changes the point. The new point is checked fresh and never accepted unchecked: when it cannot be checked, nothing changes and the admin can try again in a moment. A point that cannot take the shipment is refused with its problems; box problems are left to the plan. The change is written to the plugin's own row and history only, never to the order, the fulfillment or the customer: tell the customer yourself where to collect the parcel. The order card says when the point of the shipment is not the one the customer chose.
The storefront stores the id of the chosen point as in the data of the shipping method, for example when adding the shipping method to the cart; the checkout keeps it as . Two ways to let the customer choose:
- The PudoFinder widget of DPD: DPD's own map. It needs its own key, given by DPD's IT per domain (not the MyPudo key of the plugin), and it returns only the id of the point. The storefront then reads the point with (to show its address and to know whether it takes cash on delivery) and stores its id as .
- Your own list or map on the store routes below.
Only points in Poland in this version, in the routes and at the checkout.
Store API
Both routes ask for the publishable API key, as every Medusa route does. They answer public point data only, with .
- : the points a parcel can go to now (active, handing out parcels, in Poland), up to 25. Search by (a Polish postal code, or ) with an optional and , or by and (nearest first; MyPudo searches within 5 km), not both. may only be . keeps the points that take cash on delivery. is 1 to 25, 10 by default. Answers , where is , or .
- : one point by its id, only when a parcel can go to it now; anything else answers 404 . Answers ; says whether it takes cash on delivery.
A point has its , , (the kind of point as MyPudo gives it), , , (, , , , ), and , , , , , the opening per day (1 is Monday), in metres for a search by place, and the of its kind (weight and box).
A wrong query answers 400 . Searches are limited per client address (, then 429 with ). Searches are cached for ten minutes and points for an hour, in the process; all the store routes of one process together call MyPudo at most 120 times a minute (then 503 with ). When MyPudo does not answer, the routes answer 502 , and 503 when it is not configured.
Behind a proxy or a load balancer, set Express in your Medusa server, so that the limit counts each client and not the proxy: otherwise every customer of the store shares one limit.
Handover to the courier
Two steps. Step one is the protocol: with the session, as a PDF, under the writer. Step two, optional, is the courier order, under the writer. A store with a regular pickup by DPD stops at the protocol.
Which shipments. Outbound shipments with a label, within Poland, not in another handover, whose fulfillment Medusa has not canceled. One sender per handover: when the store ships from several stock locations with , the panel asks for one group. Up to 100 shipments. Courier, courier with cash on delivery and DPD Pickup shipments go together in one protocol.
The protocol. All or nothing: when DPD refuses one shipment, there is no protocol and no shipment changes its state. The protocol is stored with the handover and served from the database. "Print again" gives a new DPD document with a new number, so it is only a deliberate action, never a retry. The protocol prints the company and the address of the receivers; it is stored like a label and removed after . DPD fills the place of dispatch on the protocol from the account data of the paying FID.
Cancel in Medusa after the handover. Before calling DPD for the protocol, the flow writes and into the data of the fulfillment, and the provider then refuses to cancel the fulfillment (, HTTP 400 in the admin), so that Medusa does not put goods that have left back in stock. A first protocol that DPD refuses or does not answer clearly, a withdrawn shipment and a canceled handover clear the marker. Demo mode never writes it.
Ordering the courier. The plugin reads the availability for the sender's postal code (Poland only). The date is from today to 14 days ahead and the window lies wholly inside one of the ranges DPD offers, in Europe/Warsaw time. The box count and the weights come from the plan; a box over 50 kg blocks the courier order, not the protocol. When DPD does not answer about the availability, nothing is sent.
Never ordered twice. An unclear answer (a timeout, a network error, a 5xx, an answer without an order number) gives the state ; the plugin never orders again by itself, because a second courier costs money. A person checks in DPD and chooses "ordered" (optionally with the order number; without the , the order is then changed and canceled in DPD) or "not ordered". The same decision closes an order without a whose courier was called off in DPD, and an order whose change DPD refused as no longer valid. The admin shows the order number; the never leaves the server.
Changing and canceling. A new date or window; withdrawing a shipment (locally before the courier order, by changing the courier order after it, and by canceling the courier order for the last shipment); "Cancel courier" (the shipments stay handed over and another courier can be ordered); "Cancel handover" only without an active courier order. A protocol that lists a withdrawn shipment is marked out of date; "Print again" gives a current one. The plugin does not take a protocol back in DPD, because DPD has no such operation.
Do not send. A shipment with waybills that will not go leaves the candidates () and can come back. DPD cannot cancel a shipment through the API; with cash on delivery, the money will not come in.
Sandbox and demo. In the sandbox the protocol and the availability go to the DPD demo host, while the courier order, its change and its cancel are simulated in the process, because the demo host cannot order a courier. Settings and the drawer say so. A simulated order has the number followed by 11 digits; after a restart of the process, changing or canceling it ends in an unclear result that a person resolves. In demo mode everything is simulated and the protocol is a sample PDF; demo mode does not write the marker into the fulfillment data, so canceling the fulfillment in Medusa works. Handovers of the sandbox and their markers belong to the sandbox: before switching the sandbox to another mode, cancel its open handovers (with an ordered courier, "Cancel courier" first), otherwise the fulfillments of these handovers cannot be canceled in Medusa until you go back to the sandbox and do it there.
Nothing automatic. and the shipment pass never create a handover, never print a protocol and never order a courier.
Statuses
Where statuses come from. Live, from the DPD InfoServices: , one call per waybill, always the whole history (), with the descriptions in Polish. It needs , and ; without one of them live mode asks nothing, and Settings and the integration summary say "statuses not configured". The sandbox and demo mode never ask the DPD InfoServices: their statuses are simulated in the process, because DPD has no test host with events. Settings show the source of the statuses (, or ).
The status job. runs every 5 minutes, two minutes after the shipment pass. It takes outbound shipments with waybills, or , not delivered and not canceled, up to 30 days after the handover (or after their creation): after the handover each one at most every 30 minutes, before it every 2 hours. The ones asked least recently go first, up to 50 calls and 2 minutes per pass; the rest wait for the next one. Writes to Medusa left over from earlier passes need no DPD call: they get the last 20 seconds of the pass, and at least 5 of them run in every pass however slow DPD answers. Several server instances never take the same shipment (a claim in the database). A shipment that is delivered, back at the shop, canceled, marked "do not send" or older than 30 days is no longer asked about. A wrong InfoServices login stops the pass and shows in Settings until the next answered call.
Stages. , (set by the handover, without a DPD event), , , , and . A shipment with several boxes is when a waybill is, then , then only when every waybill is delivered, otherwise the lowest stage of its waybills. A waybill without any event counts as ( after the handover), so one delivered box never makes the whole shipment delivered. and of a waybill stay after a later event. DPD notifications (the codes starting with 1703, apart from 170302) never change the stage. A code the plugin does not know never writes to Medusa and never replaces a stage set by a known code: a waybill gets from it only while none of its events has a known code. DPD histories nearly always start with a known code (030103, the shipment registered), so a later unknown code usually leaves the waybill ( after the handover) and shows only as its newest status, with the DPD description; give such a code a stage with . In live mode comes only from a entry: DPD has not confirmed the code of the arrival at a Pickup point, so the built in map gives only to the simulator's in the sandbox and demo mode, and without such an entry a parcel waiting at the point stays until it is collected (). The meaning of most codes comes from the DPD documentation and from open libraries, not from a confirmation by DPD; changes the stage of a code.
Shipped and delivered in Medusa. The writer, off by default, has two switches like the other writers. "Shipped" () comes only from an event that means DPD has the parcel in its hands; never from the handover alone, from a courier window that has passed or from the time that went by, because Medusa cannot take a shipment back. "Delivered" () comes when every waybill is delivered; for DPD Pickup that is the collection from the point, not the arrival at the point (a code not confirmed by DPD). The labels of the fulfillment get the waybill without a link; the labels already there stay. Each mark is claimed on the plugin's row before Medusa's flow runs; a fulfillment someone already marked by hand is only noted. A failed flow releases the claim, keeps its message with the shipment and lights a tile; the status pass tries again every 30 minutes for 30 days after the handover (also after the delivery, without asking DPD), and "Write the status to Medusa again" does it at once. A writer armed later marks the shipments that DPD had in its hands, or delivered, in the last 30 days. A claim left by a process that stopped (older than 15 minutes, while Medusa has no shipped or delivered date) is released with an entry in the history and written again.
New waybill numbers. A redirect (230402) and a return to the sender (230403, 230408) move the parcel to a new waybill when the event carries exactly one number shaped like a DPD waybill. The plugin swaps the waybill in its place, asks the old one once more and updates in the data of the fulfillment. A redirected parcel stays at least : the first events DPD reports for the new number (the data registered) never take it back to . A parcel on its way back is and waits in Problems; its delivery means it is back at the shop and never gives "delivered" in Medusa. Once it is back, or 30 days after the handover, it moves to Returns and no longer counts as a matter waiting for a person. An event that moves the parcel without one clear number stays in the history as unclear.
Sandbox and demo. The simulator gives events from the moment of the handover, with the codes of the DPD documentation and of the libraries, plus for the arrival at a Pickup point; some shipments get a failed delivery attempt or a return with a new waybill. It keeps no state, so a restart loses nothing. In the sandbox an armed writer writes to the real development store (the only way to try it before production) and the history says "simulated"; a sandbox run on a copy of production orders marks them for real. A simulated status never mails a customer: the writer passes to Medusa, so its "shipped" and "delivered" notifications stay silent. In demo mode the writer writes only the history, and the sample rows of the seed never move.
The queue mode is not there yet. gives a warning in Settings and the statuses still go per waybill. The queue of the DPD InfoServices is shared by the channel, and confirming its events would take them away from the other systems of the shop; it needs a channel for Medusa alone.
Refresh. "Refresh the status" asks DPD about one shipment at once, outside the job. Reading needs no writer.
Events
Three events carry . The shape is a contract: fields and events may be added, never changed.
- : once per shipment, when DPD gives its waybills, or when the plugin adopts a shipment it found after an unclear answer.
- : once per change of the stage, from the status job or a refresh, with and (the id of the DPD event in the plugin's history; a subscriber drops repeats by it).
- : once, right after its , when every waybill is delivered.
The receiver's name, phone, e-mail and address are never in an event. A subscriber that writes to the outside world should skip . The example below runs in live mode only with a entry that gives the arrival at a Pickup point the stage (see Stages); in the sandbox and demo mode the simulator gives it:
Each event is emitted at most once, after the change is saved; a failed emit is logged, not repeated. comes with the returns; there are no events of the handover in this version.
Requirements
- Medusa 2.12 or newer and Node.js 20+.
- A DPD Polska business account with access to the DPD web services (login, password and the FID of the account). Demo mode runs without it. Statuses in live mode also need access to the DPD InfoServices (a login, a password and a channel from DPD).
Installation
Configuration
The plugin is registered twice with the same options object: as a plugin (the data module, the admin page, the routes and the job) and as a provider of Medusa's fulfillment module. Keep the id : the provider is then .
Run the migrations, then open DPD in the admin sidebar:
npx medusa db:migrateMissing or broken options never stop the boot: they are listed in the admin. Demo mode runs only with .
Options
Every option is optional. Numbers and booleans may come as strings from environment variables, lists as comma separated strings, objects as JSON; a value that cannot be read is ignored and listed in the admin.
Connection:
- , (default none): the DPD web services login and password (HTTP Basic). They never leave the server.
- (default none): the FID of the account, sent in the header. (default the master FID): the FID that pays for the shipments.
- (default ): (the DPD demo host) or .
- (default ): sample shipments built from the store's orders with a simulated DPD. Only turns it on: missing credentials never do.
- (default , 5000 to 45000): how long one call to DPD may take. A create that runs out of time goes to and is looked up, never sent again blindly.
- (default , 10 to 600): calls to DPD per minute from one process. A call that would wait more than 15 seconds for its turn is not sent and the shipment can be tried again.
DPD Pickup points (live mode only; the sandbox and demo mode use their catalogs):
- , (default none): the MyPudo login and password (HTTP Basic). (default none): the MyPudo key, used when the login and password are not both set. They never leave the server and are masked everywhere.
- (default , 1000 to 10000): how long one call to MyPudo may take. The checkout lets an unchecked point through, so this is also the longest a customer waits for the check.
- (default , 5 to 600): point searches per minute from one client address on the store routes.
Statuses (live mode only; the sandbox and demo mode simulate them):
- , , (default none): the DPD InfoServices login, password and channel. The password is masked everywhere; the admin only sees whether each one is set.
- (default ): does not work yet and gives a warning; statuses then still go per waybill.
- (default none): changes the stage of a DPD event code. A code outside the built in map with the stage , or also counts as "DPD has the parcel"; for a code the built in map knows, also by its prefix, only the stage changes. The stage is ignored. In live mode it is the only source of the stage .
Writes:
- (default ; in demo mode , acting on the simulation only): allows creating shipments, getting labels, looking up unclear shipments in DPD (a label and a lookup advise the parcels in DPD), the protocols of the handover and "do not send". It works only when a person also arms it in Settings.
- (default ; in demo mode , acting on the simulation only): allows ordering, changing and canceling the courier, and resolving courier orders, orders that need a person and orders without a . It works only when a person also arms it in Settings. In the sandbox the courier order is simulated also with this writer armed.
- (default ; in demo mode , writing only the history): marks Medusa fulfillments shipped and delivered from the DPD statuses. It works only when a person also arms it in Settings. In the sandbox it writes to this Medusa store.
- (default ): with the shipment writer armed, create the shipment as soon as its fulfillment is created, from a plan without problems, and let the shipment pass create the ones it missed. Plans with problems wait for a person either way.
- (default , 1 to 720): the shipment pass creates only fulfillments recorded after the shipment writer was armed and within these hours.
Shipments:
- (default none; required outside demo mode): , the sender of every shipment. : a sender per stock location id, for stores shipping from several warehouses. Ordering the courier needs a Polish postal code of the sender.
- (default the sender): , who orders the courier. defaults to the sender's company, to the sender's contact person, to the sender's phone.
- (default ): or , the label page the plan drawer offers first; the page is chosen when creating the shipment, and a stored label is not printed again in another format yet.
- (default ): the unit of the variant weights, or . (default none): , the box when the variants have no weight.
- (default ): cash on delivery currencies per destination country. (default ): the payment providers that mean "pay at the door".
- (default ): days a stored label or protocol is kept.
The other options (, ) are read and checked already, and are used by the next versions.
Write safety
- Two switches per writer. The option (, , ) is the hard one: wins and the admin cannot override it. The switch in Settings is the runtime one, stored with who flipped it and when.
- One shipment per fulfillment: one row per fulfillment before anything goes out, an atomic claim with a lease, and a reference that never changes (the fulfillment id). DPD refuses a second shipment with the same reference, and the plugin reads that refusal as "it exists" and takes the shipment over.
- Plan first: a person confirms the plan of this moment (its hash); a plan with problems sends nothing.
- One courier per handover, never sent twice: DPD has no idempotency key for a courier order, so an unclear answer gives , nothing is sent again, and a person says whether the courier was ordered.
- The handover marker: written into the fulfillment data before DPD is asked for the protocol and cleared when DPD refuses it; while it is there, Medusa may not cancel the fulfillment.
- Medusa marks once: each shipped or delivered mark is claimed on the plugin's row before Medusa's flow runs, and released with the error when the flow fails. A fulfillment marked by hand is only noted. An unknown code never marks anything.
- No way back after the pickup: once DPD has the parcel (an event that means it, a stage past other than , or the plugin's own shipped mark in Medusa), withdrawing it from a handover, "do not send", canceling the handover and putting it in a new handover are refused. A fulfillment marked shipped by hand in Medusa does not count: the plugin reads only what DPD told it. A failed pickup at the sender (the codes 0402xx to 0406xx) does not block them.
- Nothing that cannot be undone is pretended: DPD's web services cannot cancel a shipment. When a fulfillment is canceled after its shipment was created, the row stays as it is and the history says so; an unclear one is looked up to tell whether DPD has it.
Security and data
- Credentials stay on the server: masked in logs, errors and the admin, which only knows whether they are set. The InfoServices password is masked; the admin sees the InfoServices login and channel only as set or missing. The SOAP envelope never goes to the logs, the history or an answer.
- No receiver data from the DPD events: the additional data of a DPD event (, which may hold the name of the receiver) is never stored or logged; the plugin reads from it only the new waybill of a repin. The history keeps the code, the time, the depot and the DPD description. The status events of shipments no longer followed are removed after 120 days.
- Personal data stays where it lives: the receiver's name, phone, e-mail and address (and, for DPD Pickup, those of the person who collects) are read from the order when a plan is built and go only to DPD and to the plan answer (not cached). The address of a Pickup point is public data and is kept with the shipping method and the shipment. The plugin's tables keep ids, the option, the boxes, the cash on delivery amount, the reference, the waybills and the states; problems name what is wrong, never the value. Stored labels carry what DPD prints on them and are removed after . Protocols carry the company and the address of the receivers (not the name of a person); they are stored like labels, served only to the admin and without a cache, and removed after .
- The of a courier order (it allows changing and canceling the order) never goes to the logs, the history or an answer; the admin sees only the order number.
- Admin routes sit behind Medusa's admin authentication, and writes need a JSON body or the header.
- Shopper metadata is not state: a shopper may not set keys on a cart or the account through the Store API, and the point snapshot is added only by the checkout after its check.
- MyPudo credentials: the key travels in the URLs of MyPudo, so every URL, error and log line of MyPudo is masked, and no MyPudo URL is stored or answered.
What this plugin does not do (yet)
- It does not send shipments abroad, also not to DPD Pickup points outside Poland, and it does not create returns.
- It does not change a Pickup point by itself and does not tell the customer about a change.
- It does not filter the points by the weight of the cart, and it does not use the holiday filter of MyPudo: a point closed for a day within two weeks may not be listed.
- It does not hand over shipments abroad and does not order a courier abroad.
- It does not take a protocol back in DPD, does not order pallets or envelopes, and gives the protocol only as a PDF.
- It does not read the queue of the DPD InfoServices ().
- It does not add the DPD tracking link to the Medusa label, only the waybill.
- It does not track the return shipments of the shop (the next version) and emits no events of the handover.
- It does not tell the customer by itself: Medusa's and the events of the plugin let a mail plugin do it.
- It does not print a label again in another format: DPD has not yet said whether that advises the parcels again.
- It does not calculate shipping prices from DPD's price list: the shipping options' own prices apply.
Admin API
Every route is behind Medusa's admin authentication. Creating, getting a label and looking up answer 409 while the shipment writer is not allowed and armed. The same goes for printing a protocol, canceling a handover, "do not send" and restoring. Ordering the courier, a new date, canceling the courier, resolving and withdrawing a shipment from an ordered courier answer 409 while the pickup writer is not allowed and armed. The availability needs a configured client, no writer. "Write the status to Medusa again" answers 409 while the writer is not allowed and armed. "Refresh the status" needs no writer, but answers 409 when the statuses are not configured, and 502 when DPD refuses the login or gives no clear answer.
- : a shipment with its stored documents (never their bytes) and its history. The shipment also carries its waybills with their stages () and the marks of the writes to Medusa.
- : its plan with the hash, for a shipment not created yet.
- : creates the shipment from the plan that was read and gets its label.
- : gets the label of a shipment created without it. : the stored label PDF.
- : sets the boxes by hand, goes back to the automatic ones.
- : changes the point of a pending or failed Pickup shipment, checked fresh; it needs no armed writer, because nothing goes to DPD. : the point search of the admin, the same query as the store route, without its limits.
- , , : look up an unclear shipment in DPD, accept DPD's waybills of a shipment that does not match, mark a shipment as handled outside the plugin.
- : the plan of a handover for the selected shipments, with its hash.
- (, , ): the handovers. : creates a handover from the plan that was read and, with , prints its protocol.
- : one handover with its shipments and protocols.
- : prints the protocol, or prints it again as a new DPD document.
- (, ): a stored protocol PDF.
- : the courier availability for the sender of a handover. : the same before the handover is created.
- and : orders the courier, or gives the order a new date or window.
- , , : cancels the courier order, resolves an order that needs a person, cancels the handover.
- , , : "do not send", its restore, and withdrawing a shipment from its handover.
- : asks DPD about the status of one shipment now.
- : writes the shipped or delivered mark of one shipment to Medusa again.
Trademarks
DPD and the DPD logo are trademarks of their owners, used here only to identify the service this plugin connects to. This is an independent integration, not affiliated with or endorsed by DPD.
License
MIT, see LICENSE.
Changelog
0.5.0 (2026-11-09, first npm release)
Statuses from the DPD InfoServices in their own job, the stages of a shipment and of each waybill, new waybill numbers after a redirect or a return, the writer that marks fulfillments shipped and delivered in Medusa, the events , and , and the simulated statuses of the sandbox and demo mode. Full list in CHANGELOG.md.
0.4.0 (not published)
The handover to the courier within Poland: a protocol for up to 100 labeled shipments of one sender, then optionally the courier order, never sent twice, with a new date, withdrawing a shipment, canceling the courier and canceling the handover; "do not send"; the handover marker that stops Medusa from canceling a fulfillment that has left. Full list in CHANGELOG.md.
0.3.0 (not published)
DPD Pickup shipments to points in Poland, with or without cash on delivery: the point checked at the checkout (letting it through when MyPudo cannot answer), in the plan and when a person changes it in the admin; the store routes for a point search and one point; the test catalog of the sandbox and the sample catalog of demo mode. Full list in CHANGELOG.md.
0.2.0 (not published)
DPD courier shipments in Poland, with or without cash on delivery: the plan with its hash, the boxes, the labels, the unclear answers and their lookup, and the shipment pass. Full list in CHANGELOG.md.
0.1.0 (not published)
The skeleton: the provider with five options, the data module, the options with sender checks, the writers, the integration contract and the admin page in demo mode.

