Skip to content

Developer notes

Technical reference for developers who customize Mondial Relay Pickup Points & Labels. Every operation and field below is taken from the Mondial Relay documents and the schema files saved with the tests (tests/fixtures/official: Web_Services.wsdl, ShipmentRequest.xsd, ShipmentResponse.xsd and the two sample XML files). What the documents do not state is marked UNVERIFIED; see Conformance.

Item Value
Add-on id kv_mondial_relay
Function prefix fn_kv_mondial_relay_
Language variables kv_mondial_relay.*
CSS scope .kv-mr (admin), .kv-mrp (checkout picker)
PHP namespace Tygh\Addons\KvMondialRelay
Shipping service class Tygh\Shippings\Services\KvMondialRelay (module kv_mondial_relay)
Preset shipping (generated by kv new --kind integration)
Class Role
Client\BaseClient HTTP (cURL, TLS verification, timeouts), error mapping (decodeError hook), masked logging
Client\Api The two web services: searchPoints() (API 1 WSI4_PointRelais_Recherche), track() (API 1 WSI2_TracingColisDetaille), createShipment() (API 2), download() (label address), ping(), the Security hash (security()) and the API 1 status texts
Client\Soap SOAP 1.1 envelope builder and parser for API 1 (namespace http://www.mondialrelay.fr/webservice/, SOAPAction = namespace + operation)
Client\Connect API 2 request document (element order of the request XSD) and response reader (DOM; reads attributes ShipmentNumber, Status)
Client Client per company, the connection test
Accounts, Secret Credentials (test and live) sealed with AES-256-GCM; one account per store owner or per vendor
Config, Access Settings, owner mode, who may see and manage what
Shipments Order -> request mapping, label storage, return label, record-before-call idempotency, unknown-result handling (adopt, confirm nothing), tracking mapping, local cancel
Parcel Field normalisation: transliteration, allowed characters, length limits, phone patterns, street/house number split, grams, OrderNo, CustomerNo, Location code
Points Point Relais of an order: widget addresses, search, normalise, opening hours, server-side validation, storage
Installer, RateCalculator Shipping services (3) and the merchant’s own rates (the web services have no price operation)
Idempotency Per-object locks (label per order, return per shipment)
Queue, Jobs, JobException, Log Job queue (back-off 5 min / 15 min / 1 h / 3 h / 12 h), recurring tracking, log with masking
Table Purpose
?:kv_mondial_relay_accounts Credentials per company: test_id / live_id = API 2 login, test_secret / live_secret = API 2 password (sealed), test_pass / live_pass = API 1 private key (sealed), extra (JSON) = customer id, brand and sender address per mode, last connection check
?:kv_mondial_relay_log Log
?:kv_mondial_relay_jobs Queue (create_label, track)
?:kv_mondial_relay_shipments Labels and tracking: provider_ref = tracking_number = 8-digit shipment number, label_data (base64) + label_url, extra_docs (JSON: returnLabel, returnState), status C created / T in transit / D delivered / P problem / X cancelled in the store / W request sent, answer not stored yet / U result unknown
?:kv_mondial_relay_points Chosen Point Relais per order: point_id (6 digits), address, hours, country

enabled, owner_mode, debug_log, log_retention_days, label_status, core_shipment, label_format (pdf / zpl), paper_format (10x15 / A4 / A5), cod_payment, weight_default, dim_length, dim_width, dim_height, ship_days, parcel_content, send_contact, cron_key, license keys. Credentials are not settings (Connection page, Accounts). Shipping method parameters (service_params): price, tiers, free_from, countries, max_weight, delivery_text.

PHP: change_order_status_post (queues create_label at the chosen status), get_order_info (attaches the chosen point), place_order / place_suborders (store the point), delete_order, template_document_order_context_init (point in order documents), init_templater_post (only while an in-place upgrade is pending). Pre-controller checkout.pre (a Point Relais order cannot be placed without a point) and post-controller orders.post (order tab data).

Templates: backend orders:tabs_extra (order tab), addons:manage, addons:tabs_content (license card), index:styles; storefront checkout:shipping_method (picker card), orders:totals_shipping (point on the order page), index:scripts, index:styles. The picker is an AJAX POST only (kv_mondial_relay.point_select) and the widget is loaded by JavaScript when the customer opens the panel, so no cacheable page contains Mondial Relay data.

  • Another service. Add the code to Installer::services(), its delivery mode to Installer::product() and, if it is a Point Relais service, to Installer::isPickup() and Points::action(). A service with a delivery mode that needs an extra step (for example XOH) must not be added without that step.
  • Rates. The rate logic is RateCalculator::quote()/price(); replace the table with your own logic there.
  • Fields of the shipment request. Shipments::payload() builds the data array, Client\Connect::request() writes the XML in the order of the request XSD. Add new elements in the XSD sequence position; the unit tests validate every request against the XSD.
  • Options (LNG, ASS) and shipmentValue are not sent; see the notes in Client\Connect.

The base URL can be overridden for tests in config.local.php (development only; production always uses the Mondial Relay HTTPS hosts):

$config['kv_mondial_relay_base_url'] = 'http://127.0.0.1:11853';

php -S 127.0.0.1:11853 tests/mock-server/server.php starts a local stand-in that validates API 2 requests against the official request XSD and the documented field patterns, validates API 1 requests against the WSDL types, checks the Security hash with the documented algorithm (test account BDTEST13), and serves a stand-in of the widget with the same plugin name and callback (it draws no map). node tests/e2e/e2e.mjs runs the HTTP end-to-end test against it; php tests/unit.php runs the unit tests. This proves the add-on against the documents and a mock, not against Mondial Relay: no call to the sandbox or to the live service was made.

Admin templates live in design/backend/templates/addons/kv_mondial_relay/, storefront templates in var/themes_repository/responsive/templates/addons/kv_mondial_relay/. Do not edit them in a store; they are replaced on update.

Sources: [DC] WEB SERVICE DUAL CARRIER V-2.7.1 (June 2024; page numbers from its contents); [WS] WEB SERVICE V-5.14 (January 2025); [W] WIDGET V4.1 (December 2019); [P] Presentation of WebServices V-1.1 (April 2025); [XSD-Q] Mondial-Relay-Shipment-API-.Request.1.0.xsd; [XSD-R] the matching Response.1.0.xsd; [WSDL] Web_Services.wsdl.

Operation Endpoint Source
API 2 ShipmentCreationRequest (labels, outbound and return) POST https://connect-api-sandbox.mondialrelay.com/api/shipment (test), https://connect-api.mondialrelay.com/api/shipment (live). Headers Accept: application/xml, Content-Type: text/xml, body UTF-8 without BOM [DC] “Service overview” p. 9, “Service request specifications” p. 18
API 1 WSI4_PointRelais_Recherche POST https://api.mondialrelay.com/Web_Services.asmx (SOAP 1.1) [WS] “General description” p. 6, “Point Relais search” p. 9-13; [WSDL]
API 1 WSI2_TracingColisDetaille same [WS] “Parcel tracking” p. 26; [WSDL]
Widget MR_ParcelShopPicker script https://widget.mondialrelay.com/parcelshop-picker/jquery.plugin.mondialrelay.parcelshoppicker.min.js loaded in the customer’s browser [W] “Utilisation” p. 5
Label download GET of the address in Label/Output (PdfUrl), only on mondialrelay.* hosts, https [DC] “Output entity” p. 19-20

Not used: API 1 WSI2_CreationExpedition, WSI2_CreationEtiquette, WSI3_GetEtiquettes ([WS] V-5.11: stopped; “Accounts created from 23/12/2024 will be blocked for the shipment creation with this API”), WSI2_RechercheCP, WSI2_STAT_Label.

API 2 request: ShipmentCreationRequest (namespace http://www.example.org/Request)

Section titled “API 2 request: ShipmentCreationRequest (namespace http://www.example.org/Request)”
Element / attribute Type, limit, pattern (document) How the add-on fills it Source
Context/Login String, mandatory API 2 login of the Connection page [DC] p. 11, [XSD-Q]
Context/Password String, mandatory API 2 password (never logged) [DC] p. 11
Context/CustomerId String, mandatory, max 8, ^[0-9A-Z]{2}[0-9A-Z]{6}$ Customer id of the Connection page. The form accepts 2 to 8 letters and digits (looser than the document pattern) [DC] p. 11, [XSD-Q]
Context/Culture String, mandatory, 5, ^[a-z]{2}-[A-Z]{2}$ Fixed fr-FR (as in every example) [DC] p. 11
Context/VersionAPI Enumeration, mandatory Fixed 1.0 (“Version that match this document is 1.0”) [DC] p. 11
OutputOptions/OutputFormat Enumeration. PdfUrl: 10x15, A4, A5; ZplCode: Generic_ZPL_10x15_200dpi; IplCode: Generic_IPL_10x15_204dpi Setting “Label size” (10x15, A4, A5) or Generic_ZPL_10x15_200dpi [DC] p. 12
OutputOptions/OutputType Enumeration: ZplCode, PdfUrl, IplCode PdfUrl or ZplCode. IplCode, the Monarch printer models and QRCode are not offered [DC] p. 12
ShipmentsList/Shipment/Options Option Key (ASS, LNG) / Value, optional, “not for returns” Not sent [DC] p. 13, 17
Shipment/OrderNo String, optional, max 15, ^(|[0-9A-Z_ -]{0,15})$ O<order id>-<shipment row id> (return: R...), cut at 15 characters. Deterministic: the reference to look for in Connect after an unknown result [DC] p. 13
Shipment/CustomerNo String, optional, max 9, ^(|[0-9A-Z]{0,9})$ K<order id>, cut at 9 characters [DC] p. 13
Shipment/ParcelCount Integer, mandatory, ^[0-9]{1,2}$; multi-parcel only for 24L, LD1, LDS Always 1 [DC] p. 13
Shipment/ShipmentValue (shipmentValue.amount, .currency) Float / EUR, optional in the PDF Not sent. The XSD marks it required and its currency list is a placeholder (value); only the ASS option needs it. See Conformance [DC] p. 13, [XSD-Q]
Shipment/DeliveryMode@Mode String, mandatory, 3, ^[0-9A-Z]{3}$ 24R, 24L, HOM; return label: LCC [DC] p. 13-14
Shipment/DeliveryMode@Location String, optional, max 10, ^[0-9A-Z]{0,10}$, mandatory for 24R, 24L, XOH 24R/24L: <country>-<point number without leading zeros> (for example FR-66974); HOM and LCC: empty. UNVERIFIED against the live service: the examples show FR-66974 for the point the widget calls 066974; the XSD comment shows FR00001 [DC] p. 13, example p. 27, [XSD-Q]
Shipment/CollectionMode@Mode String, mandatory, 3 CCC (merchant collection); return label: REL [DC] p. 14
Shipment/CollectionMode@Location String, optional, default “Auto” outbound: empty; return: Auto [DC] p. 13
Parcels/Parcel/Content String, optional, max 40, ^[0-9A-Z_\-'., /]{0,40}$ Setting “Parcel content text”, cleaned and cut at 40; omitted when empty [DC] p. 14
Parcel/Length, Width, Depth (Value, Unit="cm") Integer, optional (mandatory for Poland), max 10 From the package size settings when greater than 0 and below 1000; otherwise omitted [DC] p. 14, [XSD-Q]
Parcel/Weight (Value, Unit="gr") Integer, mandatory, ^[0-9]{0,10}$, “Minimum 10grs” Sum of product weight x quantity in grams (weight unit of the store taken into account), at least 10; the setting “Default parcel weight” when no product has a weight [DC] p. 14
Shipment/DeliveryInstruction String, optional, max 30 Not sent [DC] p. 14
Sender/Address, Recipient/Address AddressType, XSD order: Title, Firstname, Lastname, Streetname, HouseNo, CountryCode, PostCode, City, AddressAdd1, AddressAdd2, AddressAdd3, PhoneNo, MobileNo, Email. Empty elements are omitted Outbound: sender = Connection page (or company data), recipient = delivery address of the order. Return: swapped ([P] section 4: the sender is the end customer, the recipient the return address) [DC] p. 15-17, [XSD-Q]
Address/Title String, optional Not sent [DC] p. 15
Address/Firstname, Lastname Max 32 each / 40 together in the table (XSD: 30 each); error 10062: Title + first + last name max 30 Cleaned; together at most 30 characters (first name cut to 12 when needed) [DC] p. 15, error 10062
Address/Streetname + HouseNo Street max 40, house number max 10; error 10063: HouseNo + StreetName max 30; Netherlands: the number goes at the end of the street field Street line split into street and number; together at most 30 characters (overflow goes to AddressAdd3); NL: the number is appended to the street [DC] p. 15, error 10063
Address/CountryCode ^[A-Z]{2}$ ISO 3166-1 alpha-2 of the order address (Monaco is handled by Mondial Relay as FR) [DC] p. 15, [WS] p. 5
Address/PostCode Max 10 Cleaned, cut at 10 [DC] p. 15
Address/City Max 30 Cleaned, cut at 30 [DC] p. 15
Address/AddressAdd1 Max 30. “Name. Do not fill it if Firstname/Lastname are filled” Company name only when no first and last name exist [DC] p. 16
Address/AddressAdd2 Max 30, additional name Company name when a person name exists [DC] p. 16
Address/AddressAdd3 Max 30, additional address information Street overflow and the second address line [DC] p. 16
Address/PhoneNo, MobileNo Max 20, pattern per country (“Regular expression for phone numbers”); XSD \+\d{3,20}; PhoneNo mandatory for home delivery Normalised to +<dialing code><number> and checked against the country table of the document (FR, ES, BE, DE, LU, PT, AT, UK, IT, NL, IE, MC, CH, PL); a mobile prefix goes to MobileNo, otherwise PhoneNo. Recipient: always for home delivery (outbound), otherwise only with “Send e-mail address and mobile number”. Sender: from the Connection page [DC] p. 16-17
Address/Email Max 70, ^[\w\-\.\@_]{7,70}$ Recipient: only with the privacy setting on; sender: the merchant’s own [DC] p. 16

API 2 response: ShipmentCreationResponse (namespace http://www.example.org/Response)

Section titled “API 2 response: ShipmentCreationResponse (namespace http://www.example.org/Response)”
Element / attribute Use Source
ShipmentsList/Shipment@ShipmentNumber The 8-digit shipment number: stored as provider_ref and tracking number. Present in the PDF example, not declared in the response XSD (UNVERIFIED if the live service always sends it); an answer without a valid 8-digit number is parked as “result unknown” [DC] p. 28, [XSD-R]
Shipment/LabelList/Label/Output PdfUrl: an address to fetch the PDF from; ZplCode: base64 ZPL. Fetched immediately (PDF) and stored [DC] p. 19-20, example p. 29
Label/RawContent/Barcodes/Barcode (Type, DisplayedValue, Value, CarrierCode) Read by the parser, not stored (the barcode is part of the label) [DC] p. 19, [XSD-R]
Label/RawContent/LabelValues (Key, Value) Read by the parser, not stored [DC] example p. 29, [XSD-R]
StatusList/Status (Code, Level, Message) Level “Warning” is logged and does not stop the label; any other level (“Error”, “Critical Error”) is a rejection with the code and message; codes -1 and 99999 count as an unknown outcome [DC] p. 21-26
HTTP status 5xx, 408, 425, 429 and network errors are technical errors (“the user of the service can try to call the service later again”); 425 and 429 are treated as rejections, the others as unknown outcome [DC] p. 22

Raw content other than the above (Sender, Recipient, Parcel, RoutingArguments) is not used.

API 1 WSI4_PointRelais_Recherche (SOAP, namespace http://www.mondialrelay.fr/webservice/)

Section titled “API 1 WSI4_PointRelais_Recherche (SOAP, namespace http://www.mondialrelay.fr/webservice/)”

The 16 SOAP parameters in WSDL order are listed below with the documented Security order. Security = upper case MD5 of the concatenation of the parameter values in documentation order (empty values add nothing) followed by the private key: [Enseigne][Pays][NumPointRelais][Ville][CP][Latitude][Longitude][Taille][Poids][Action][DelaiEnvoi][RayonRecherche][TypeActivite][NombreResultats][CLE PRIVEE] ([WS] “Generating the security key” p. 7 and the parameter table within p. 9-13). NACE is in the WSDL between TypeActivite and NombreResultats (“Non applicable”) and is sent empty; it is not part of the Security string.

# Parameter Document (type, pattern) How the add-on fills it
1 Enseigne O, 8, ^[0-9A-Z]{2}[0-9A-Z ]{6}$ Brand of the Connection page
2 Pays O, ^[A-Za-z]{2}$ Country of the delivery address (checkout validation: country of the cart)
3 NumPointRelais F/O, ^[0-9]{6}$, with Pays for one point The 6-digit point number when validating the customer’s choice; empty otherwise
4 Ville F/O, “NON APPLICABLE” Empty
5 CP F/O, depends on the country Postal code of the search (the point’s postal code for the XL check)
6 Latitude F/O, ^-?[0-9]{2}\.[0-9]{7}$ Empty
7 Longitude F/O Empty
8 Taille F, “Do not use unless specified by Mondial Relay” Empty
9 Poids F, grams, ^[0-9]{1,6}$, 15 g minimum Sent only when a weight of at least 15 g is given
10 Action F, ^(SMA|APM|REL|MED|24R|24L|XOH)$ 24R or 24L by the shipping method
11 DelaiEnvoi F, ^-?[0-9]{2})$ Setting “Days between the order and the hand-over” as two digits, only when above 0
12 RayonRecherche F, ^[0-9]{1,4}$, default 50 km, 0 = no filter Empty (default 50 km)
13 TypeActivite F, ^(\d{3},|\d{3})*$ Empty
14 NACE NA Empty (not in the Security string)
15 NombreResultats O, max 30 1 to 30 (1 for one point, 30 for the XL check, 1 for the connection test)
16 Security O, ^[0-9A-Z]{32}$ As above

Response used: WSI4_PointRelais_RechercheResult: STAT (0 = success; any other value is an error with the text of the status table), PointsRelais/PointRelais_Details: Num (6 digits), LgAdr1 + LgAdr2 (name), LgAdr3 + LgAdr4 (address), CP, Ville, Pays, Latitude, Longitude (the widget sample uses a decimal comma, converted), Distance (meters per [WS]; stored, not shown), Horaires_Lundi … Horaires_Dimanche (string array of 4: opening and closing time of slot 1, opening and closing time of slot 2). Not used: Localisation1/2, TypeActivite, NACE, Information, Informations_Dispo, URL_Photo, URL_Plan. The document names Lgdr1 and Horaire_ Lundi; the WSDL names LgAdr1 and Horaires_Lundi; the add-on follows the WSDL. The format of the opening-hour strings is UNVERIFIED (the WSDL says ArrayOfString): HHMM is assumed, HH:MM is accepted, 0000 means none.

Parameter Document How the add-on fills it
Enseigne O, 8, ^[0-9A-Z]{2}[0-9A-Z ]{6}$ Brand
Expedition O, ^[0-9]{8}$ The 8-digit shipment number
Langue O, ^[A-Z]{2}$, “Language requested for tracking” Fixed FR. The supported languages are UNVERIFIED
Security O, ^[0-9A-Z]{32}$, string [Enseigne][Expedition][Langue][CLE PRIVEE] As above

Response used: STAT (accepted: 0, 80 recorded parcel, 81 parcel in process at Mondial Relay, 82 delivered parcel, 83 anomaly; 94 unknown parcel keeps the stored status; every other value is an error), Libelle01, and Tracing/ret_WSI2_sub_TracingColisDetaille rows with Libelle, Date, Heure, Emplacement (the document names them Tracing_Libelle, Tracing_Date, Tracing_Heure, Tracing_Lieu; the WSDL names are used). The latest row becomes the status text; the rows (newest first) are the event history. [WS] p. 26: “the API return the 5 biggest steps”; [P] section 3: at most 4 to 6 queries per shipment and day, no batch use, completed shipments are not queried again.

Option Document Value used
Target Yes, jQuery selector that receives the point ID A hidden element of the picker panel
Brand Yes, customer code, 8 characters padded with spaces on the right Brand of the Connection page padded to 8 characters
Country No, default FR Country of the delivery address (default FR)
AllowedCountries No, ISO codes separated by commas The same country only (the point must be in the delivery country, status 92)
ColLivMod No, default 24R (L), 24L (XL) 24R or 24L by the shipping method
NbResults No, default 7 "7"
Responsive No, default false true
ShowResultsOnMap No, default true true
DisplayMapInfo No, default true true
PostCode No, postal code for a default search Postal code of the delivery address
SearchDelay No, days between search and drop-off Setting “Days between the order and the hand-over”, only when above 0
OnParcelShopSelected Callback, data object with ID, Nom, Adresse1, Adresse2, CP, Ville, Pays, Lat, Long Only data.ID (6 digits, for example 066974) is read and posted to kv_mondial_relay.point_select; the server looks the point up again and stores its own answer
Method MR_RebindMap Re-draws the map of a widget started in a hidden panel Triggered after the widget starts

Not used: TargetDisplay, TargetDisplayInfoPR, EnableGeolocalisatedSearch, Weight, CSS, MapScrollWheel, MapStreetView, EnableGmap, OnNoResultReturned, OnSearchSuccess, methods MR_SetParams, MR_DoSearch. The document asks the page to load jQuery 2.2.4 and an unversioned Leaflet from unpkg; the add-on uses the jQuery of the store and Leaflet 1.9.4 from unpkg.com; compatibility of the widget with that jQuery and Leaflet version is UNVERIFIED. The brand BDTEST (test) makes the widget show a warning ([W] p. 13).