Filters and actions
Choose the stage that matches your customization. Each stage and hook below links to its detailed contract and example.$is_return is false for outbound and true for return wherever the signature includes it. A combined booking can run a callback twice, once for each direction. Events with a Booked_Shipment instead expose $shipment->is_return().
smart_send_booking_completed means Smart Send has created one shipment. It fires before the plugin saves its booking information to the WooCommerce order. Use smart_send_order_fulfilled when you need the final order-side result, including an outbound success with a return failure.→ states the required return type. Actions have no useful return value. Examples are independent customizations, not a file to install in full.
Open a hook and select Description for its contract or Example for the PHP customization and usage guidance.
Checkout availability and rates
woocommerce_shipping_smart_send_shipping_is_available
woocommerce_shipping_smart_send_shipping_is_available
- Description
- Example
(bool $is_available, array $package, Smart_Send\Shipping_Method\Method $method) → boolRuns after the method’s shipping-class and customer-role checks. Return false to hide this Smart Send instance for the package; return the incoming value to preserve its existing restrictions. Returning true does not create a price outside the weight table. Checkout only; no booking or order updates. This example additionally limits the method to Denmark.woocommerce_shipping_smart_send_shipping_is_free_shipping
woocommerce_shipping_smart_send_shipping_is_free_shipping
- Description
- Example
(bool $is_free, array $package, Smart_Send\Shipping_Method\Method $method) → boolRuns after the configured minimum/coupon condition is evaluated, when the cart weight is allowed. true selects Flat fee cost, which is not necessarily zero; false uses normal weight-price calculation. It does not override zone, role, class or weight availability. The example disables the flat-fee branch, preserving ordinary rate calculation.woocommerce_smart_send_shipping_shipping_add_rate
woocommerce_smart_send_shipping_shipping_add_rate
- Description
- Example
(Smart_Send\Shipping_Method\Method $method, array $rate) → voidRuns at the end of a Smart Send rate calculation. $rate contains id, label, cost, meta_data and package. It can run even when weight rules produced no rate, so check $method->rates before deriving an extra option. The example adds 10 in the store currency to an existing rate, before WooCommerce tax calculation. It preserves the original service metadata; it does not book a different carrier service.Pickup points
smart_send_pickup_point_search_params
smart_send_pickup_point_search_params
- Description
- Example
(array $params) → arrayRuns before a nearest-point API lookup when a token is configured. Keys: carrier, country, postal_code, street (strings) and city (string or null). Return all keys. The API determines result count; trim results with smart_send_pickup_points_found. Search parameters do not rewrite the customer’s order address. This example removes surrounding postal-code whitespace.smart_send_pickup_points_found
smart_send_pickup_points_found
- Description
- Example
(Smart_Send\Delivery\Pickup_Point[] $points, array $params) → Smart_Send\Delivery\Pickup_Point[]Runs after a non-empty API result has become typed points, before session caching/display. Return a reindexed list of compatible Pickup_Point objects. The plugin removes objects that do not match the lookup’s carrier/country. It does not call this filter for an empty API result. Reordering influences Select Default only when no compatible explicit customer choice exists; this is not a way to revoke an existing compatible selection.smart_send_pickup_point_label
smart_send_pickup_point_label
- Description
- Example
(string $label, Smart_Send\Delivery\Pickup_Point $point) → stringRuns when a pickup label is formatted, after Dropdown format. Return plain text, not HTML or pre-escaped entities. Each renderer escapes its output. This affects display, not the point’s identity or saved address. Identity is the exact agent number together with carrier and country.smart_send_pickup_point_timeout
smart_send_pickup_point_timeout
- Description
- Example
(int $seconds) → int|floatDefault: 4 seconds. Runs for both nearest-point and single-point API requests. Return a positive timeout in seconds. Increasing it can lengthen checkout waits; it does not guarantee results. The example allows six seconds.Shipping method settings
woocommerce_settings_api_form_fields_smart_send_shipping
woocommerce_settings_api_form_fields_smart_send_shipping
- Description
- Example
(array $fields) → arrayWooCommerce calls this when reading the global Smart Send settings field definitions. Return the complete field array. Editing a field’s description/default does not change a previously saved value or implement behavior for a new field. The example adds guidance to the existing validation button.woocommerce_shipping_instance_form_fields_smart_send_shipping
woocommerce_shipping_instance_form_fields_smart_send_shipping
- Description
- Example
(array $fields) → arrayWooCommerce calls this when reading a shipping-zone instance’s fields. Return the complete definitions. The example clarifies the customer-facing title; it changes neither the booked service nor saved settings.Fulfillment decisions
smart_send_fulfillment_shipping_methods
smart_send_fulfillment_shipping_methods
- Description
- Example
(array $carriers, WC_Order $order, bool $is_return) → arrayRuns separately for the outbound and return service lists on the order screen. Shape: each carrier has code, name, services; each service has code, name, addons (currently an empty array). A booking method is carrier_service, for example postnord_agent. Return the filtered carrier list. The resolved selected method is always re-added if missing, even if you return []. This narrows the UI; it is not an authorization boundary. Enforce booking rules in smart_send_delivery_details. The example offers only PostNord for outbound, subject to that selected-method safeguard.smart_send_delivery_details
smart_send_delivery_details
- Description
- Example
(Smart_Send\Delivery\Delivery_Details $details, WC_Order $order, bool $is_return) → Smart_Send\Delivery\Delivery_DetailsRuns once per attempted direction after stored configuration, resolved service and submitted overrides are merged, before pickup validation and booking. Return the details object. Use set_shipping_method(), set_pickup_point() or set_parcel_plan(); use clear_pickup_point() for an explicit clear in a partial details object. Throw Smart_Send\Booking\Exceptions\Booking_Exception to reject a business rule before booking. Filter changes affect this booking; they are not automatically persisted. See delivery details and persistence.smart_send_parcel_default_weight
smart_send_parcel_default_weight
- Description
- Example
(float $weight, Smart_Send\Delivery\Parcel_Spec $spec, WC_Order $order) → floatRuns per parcel without an explicit weight. Input is the allocated items’ total in kg, possibly zero. Return a finite usable weight including packaging. An explicit Parcel_Spec::set_weight() or order-screen weight bypasses the filter. An allocated deleted product with unknown weight produces a validation error before the filter; provide an explicit positive parcel weight instead. There is no direction argument; the filter can run for outbound and return.Order data for booking
smart_send_order_receiver
smart_send_order_receiver
- Description
- Example
(array $shipping_address, int $order_id) → arrayRuns when reading the order’s shipping address, before phone/email fallback and conversion to receiver data. Uses WooCommerce address keys such as first_name, last_name, company, address_1, address_2, postcode, city, country, and optional phone/email. Return the complete address. The second argument is the order ID, not a WC_Order. Both directions use the same reading stage; this filter does not save the address.smart_send_receiver_phone
smart_send_receiver_phone
- Description
- Example
(string|null $phone, WC_Order $order) → string|nullRuns after choosing shipping phone, or billing phone when shipping and billing countries match, then trimming whitespace. Return a phone number or null. No direction flag is supplied. The example removes spaces without guessing a country calling code.smart_send_payload_receiver
smart_send_payload_receiver
- Description
- Example
(array $receiver, WC_Order $order) → arrayRuns after receiver mapping and phone/email fallback. Keys: company, name_line1, name_line2, address_line1, address_line2, postal_code, city, country (strings), phone and email (string or null). Return all keys. This is plugin-level data, not a raw HTTP payload, and it is used in either direction. The example removes accidental whitespace around a non-null email.smart_send_payload_items
smart_send_payload_items
- Description
- Example
(array[] $items, WC_Order $order) → array[]Runs after reading one row per order line, before allocation to parcels, in either direction. Return the same identities and valid quantities; use smart_send_delivery_details to distribute them. See the item row schema. Net/tax values are discounted line totals, not unit prices. The example trims a customs description without fabricating one for a deleted product.smart_send_payload_totals
smart_send_payload_totals
- Description
- Example
(array $totals, WC_Order $order) → arrayRuns after order totals have been derived and negative net/tax values clamped to zero. Return all keys in the totals schema. Later values are used as returned; preserve reconciliation and non-negative amounts. Order-level fees are included in shipment totals, whereas parcel totals contain allocated merchandise. The example logs only the currency and order total, leaving the booking values unchanged.smart_send_shipment_freetext
smart_send_shipment_freetext
- Description
- Example
(string|null $freetext, WC_Order $order) → string|nullRuns when reading text for the label, in either direction. Input is the customer’s order comment when Include order comment on label is enabled, otherwise null. Return text or null; do not return HTML. This does not control WooCommerce order-history notes. The example omits customer comments from labels.Booking request and events
smart_send_booking_request
smart_send_booking_request
- Description
- Example
(Smart_Send\Booking\Shipment $shipment, WC_Order $order, bool $is_return) → Smart_Send\Booking\ShipmentRuns after data extraction and parcel construction, immediately before translation into the API request. Return a Shipment. Prefer earlier filters for allocation/weight rules because this is after parcel validation. The example adds an outbound-only internal reference; it does not update the order or persist delivery settings.smart_send_booking_completed
smart_send_booking_completed
- Description
- Example
(Smart_Send\Booking\Booked_Shipment $booked, Smart_Send\Booking\Shipment $request, WC_Order $order) → voidRuns once per successfully booked direction, after the API response is mapped and before order-side persistence or document copying. Use $booked->is_return() for direction. It does not mean the whole outbound/return run succeeded, and a document’s local copy is not ready yet. Do not throw from the listener: a shipment already exists. Use smart_send_order_fulfilled when you need stored order results.smart_send_booking_failed
smart_send_booking_failed
- Description
- Example
(Smart_Send\Booking\Exceptions\Booking_Exception $exception, Smart_Send\Booking\Shipment $request, WC_Order $order) → voidRuns when the booking API call throws a handled HTTP client exception, just before it is rethrown as Booking_Exception. Read getMessage(), errors() (field → message list), and response_id() (string or null). This is not an all-failures event: local allocation, pickup or delivery validation can fail before the API call. No direction boolean is provided. The example logs a response ID, without address data or field values.Order side effects and final result
smart_send_fulfillment_save_documents
smart_send_fulfillment_save_documents
- Description
- Example
(bool $save, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → boolRuns after successful booking and persistence of submitted delivery overrides, before document-copy attempts and shipment-history persistence. Defaults to Save a copy of the PDF for either direction. Return false to skip local copies. A copy failure adds a warning; the booked shipment remains fulfilled and document URLs fall back to Smart Send. The example keeps documents remote.smart_send_fulfillment_order_note
smart_send_fulfillment_order_note
- Description
- Example
(string $note_html, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → stringRuns after shipment history is saved, before the native order note is added. Return safe HTML/text, or '' to omit the note. Notes are saved using WC_Order::add_order_note() when the caller requests a note. WooCommerce’s history refreshes after a page reload; the Smart Send result can appear immediately. The example writes a short plain-text note for either direction.smart_send_fulfillment_tracking
smart_send_fulfillment_tracking
- Description
- Example
(bool $push, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → boolRuns after the order-note step, before forwarding parcel tracking to the optional WooCommerce Shipment Tracking plugin. Default: true outbound, false return. This does not create live tracking updates or install that plugin. Returning false leaves the booked shipment’s own tracking data intact. The example disables forwarding.smart_send_fulfillment_order_status
smart_send_fulfillment_order_status
- Description
- Example
(string|false $status, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → string|falseRuns after tracking. Return a registered WooCommerce status such as wc-completed, or false to leave the order unchanged. Default: configured Set order status after label print for outbound; false for return. Updating status can trigger WooCommerce/third-party status hooks and emails. The example prevents Smart Send from changing status for either direction.smart_send_order_fulfilled
smart_send_order_fulfilled
- Description
- Example
(WC_Order $order, Smart_Send\Fulfillment\Fulfillment_Result $result) → voidRuns once after all attempted directions and their order-side steps, when at least one direction was fulfilled. A total failure does not fire it. It can carry outbound success alongside return failure. Inspect get_outbound_shipment(), get_return_shipment(), shipments(), get_steps($shipment), get_order_note_id($shipment) and get_warnings($shipment). get_validation_errors($is_return) and get_error_details($is_return) describe failures. See the booked result contracts; do not assume every optional step ran.Environment, logging and plugin links
smart_send_api_endpoint
smart_send_api_endpoint
- Description
- Example
(string $host) → stringRuns when constructing the API client. Default host: https://app.smartsend.io. Return the scheme and hostname only, for example https://app.smartsend.dev; the client appends the API version path. Applies to authentication, pickup lookup and booking. Use credentials for the selected environment; a staging site alone does not change this host.smart_send_sslverify
smart_send_sslverify
- Description
- Example
(bool $verify) → boolDefault: true. Runs when preparing WordPress HTTP request options. Keep certificate verification enabled for production and sandbox. The example explicitly preserves verification; fix an invalid server certificate or CA configuration rather than disabling verification.smart_send_logging
smart_send_logging
- Description
- Example
(string $message, string $level, array $context) → string|null|falseRuns only for entries enabled by the plugin’s logging policy. $level is a WooCommerce log level; $context includes source (smart-send-logistics) and plugin version. Return a rewritten message, or null/false to suppress the entry. This filter cannot enable disabled entries or replace the context by returning an array. The example suppresses debug messages only.smart_send_configuration_url
smart_send_configuration_url
- Description
- Example
(string $url) → stringRuns when building the Smart Send row’s configuration guide link on the WordPress plugins screen. Default: https://smartsend.io/woocommerce/configuration/. Return a URL, not HTML. It does not change the API endpoint. The example routes the link to the local Smart Send settings screen.smart_send_support_url
smart_send_support_url
- Description
- Example
(string $url) → stringRuns for the support link on the WordPress plugins screen. Default: https://smartsend.io/support/. Return a URL; the renderer escapes it. The example points to a support page on your own shop; create that page before using the snippet.ss_in_plugin_update_message
ss_in_plugin_update_message
- Description
- Example
(string $notice_html) → stringRuns when Smart Send displays a major-version update notice in the plugins list. Return trusted, safe HTML: the filtered result is rendered as HTML without another sanitization pass. The example appends static guidance. This is a notice hook, not a shipping/booking hook.Data contracts
The six order-reading filters above do not receive a return flag. They read the same order data for either direction.smart_send_payload_totals and smart_send_shipment_freetext run only when item data is non-empty. Use smart_send_booking_request for a final direction-specific adjustment.
Item rows
Item rows
smart_send_payload_items receives these keys on each row:Totals
Totals
smart_send_payload_totals receives floats subtotal_net_amount, subtotal_tax_amount, shipping_net_amount, shipping_tax_amount, total_net_amount, total_tax_amount, plus the string currency. Subtotal excludes shipping and includes non-shipping order fees. Ordinarily subtotal + shipping = total, separately for net and tax; clamping negative values can take precedence. Including-tax amounts are net + tax. Preserve those relationships if changing totals.Integration reference
This background describes platform hooks used by Smart Send, not additional public Smart Send customization hooks.WooCommerce integration points
WooCommerce integration points
Optional WooCommerce Subscriptions
Optional WooCommerce Subscriptions
Verification scope
Verification scope
Metadata
Smart Send stores different data on the order, its shipping items and the catalog products. The keys below describe those records; they are not interchangeable. Prefer the documented hooks and PHP API when changing booking behavior. Use WooCommerce CRUD objects when inspecting metadata so your integration works with both HPOS and traditional order storage. For order reads and intentional updates, follow WooCommerce’s HPOS recipe book : obtain theWC_Order, use its metadata methods, and save through the object. Do not assume orders are WordPress posts.
Shipping-item configuration
These values belong to eachWC_Order_Item_Shipping, not to WC_Order. WooCommerce copies them from the chosen Smart Send rate when it creates the shipping item.
$shipping_item->get_meta( $key, true ); use SS_SHIPPING_WC()->method_resolver() when you need the resolved booking service, including the separate mapping for WooCommerce’s native Free Shipping method.
Order configuration and booking results
Read these fields from aWC_Order obtained with wc_get_order(). Delivery configuration is managed by Smart_Send\Delivery\Order_Meta; booking results are managed by Smart_Send\Fulfillment\Shipment_IDs.
SS_SHIPPING_WC()->shipment_ids()->get( $order, false ) for the latest outbound ID, true for return, or labels( $order ) for the history. The ID reader returns an empty string when no ID is stored.
For the distinction between submitted values, filter changes and persistent data, see delivery details and persistence.
Pickup-point object
Pickup-point object
agent_no, company, address_line1, address_line2, postal_code, city and country. A point may also contain id, carrier, name_line1, name_line2, distance, coordinates and opening_hours; do not assume every optional property is present. Country is an ISO 3166-1 alpha-2 code. Coordinates have latitude and longitude; opening-hour rows have day, opens and closes.Use SS_SHIPPING_WC()->order_meta()->read( $order )->get_pickup_point() for a Smart_Send\Delivery\Pickup_Point or null. The typed object supports accessors and to_array() without requiring callers to depend on every raw property. For booking changes, use smart_send_delivery_details; changing only the raw agent number is not a substitute for resolving and validating a compatible pickup point.Stored colli allocation
Stored colli allocation
123 in one colli. That ID is local to the order; it is neither a product ID nor a variation ID.reference and the optional item name are labels, not item identities. Quantities and order-item IDs are positive integers. Parcel_Plan::from_array() parses the canonical shape; allocation must also be checked against the current order’s item IDs and quantities. Saving through Order_Meta strips the four measurement fields to null. An empty specs list means one parcel containing all items.Do not copy this array unchanged to another order. If items or quantities change, an incompatible saved allocation requires a reset before booking. See delivery details and persistence for allocation rules and the measurements that apply only to a booking.Renewals and fields owned by other integrations
Renewals and fields owned by other integrations
_ss_shipping_label_id, _ss_shipping_return_label_id and _ss_shipping_labels from renewal metadata. It preserves reusable delivery configuration and remaps parcel allocations to the renewal’s new order-item IDs. If that mapping cannot be verified, ss_shipping_order_parcels can contain an internal unmapped_subscription_plan wrapper that forces an explicit reset. This is an error marker, not a supported parcel-plan format to write._smart_send_renewal_source_item is a temporary internal product-order-item marker with order_id and item_id; the integration removes it after processing the copied items. Do not use it as a persistent integration field._wc_shipment_tracking_items belongs to WooCommerce Shipment Tracking. Smart Send uses that extension’s API for tracking and excludes copied tracking records from renewals; it does not define the extension’s metadata schema. _vc_aio_options belongs to vConnect and is read for compatibility when resolving delivery details. Neither field is a Smart Send-owned write contract.Delivery details and persistence
Delivery details and persistence
smart_send_delivery_details runs. Following successful booking, the submitted pickup selection and parcel item allocations are saved. The submitted method, parcel weights and dimensions apply only to the current booking. Failed booking does not save those overrides. The filter’s returned object determines what is booked, but it does not itself determine what is saved.For a combined outbound/return request, the submitted parcel plan applies to both directions unless a separate return plan overrides it. A null or empty plan means one parcel with all order items. A single spec with no allocations also includes all items and can supply explicit measurements. Multiple specs require complete allocation: every order unit exactly once, positive whole quantities, and no duplicate order-item row within a spec. Unknown order-item IDs and under-/over-allocation are rejected.Product customs information
These fields belong to aWC_Product or WC_Product_Variation, not an order or shipping item.
wc_get_product() and the product’s get_meta() for reading. To save an intentional product-data change, use update_meta_data() followed by the product’s save(); setting a value does not determine whether it is the correct customs classification.
Booking reads the current catalog values. A variation’s value takes precedence unless it is '' or null, in which case the parent product’s value is used. The plugin’s product editor supplies the fields on the main product’s Shipping tab; it does not add a separate editor for each variation. These fields are not snapshots copied onto order lines. A deleted catalog product cannot supply its customs data. See the merchant guide to customs fields.
API
Use these PHP APIs inside WordPress to read Smart Send data for an existingWC_Order. Smart Send and a supported WooCommerce version must be active. Call the examples after Smart Send initializes on init at priority 0, for example from an init callback at priority 10 or a later order hook. If you start with an order ID, load it with wc_get_order($order_id) and check that the result is a WC_Order.
These reads use WooCommerce’s order and item APIs, so they work with HPOS. They do not book shipments or contact the Smart Send API. The example functions use a my_shop_ prefix; choose your own prefix in your integration.
Read the order's pickup point
Read the order's pickup point
- Description
- Example
SS_SHIPPING_WC()->order_meta()->read($order) returns Smart_Send\Delivery\Delivery_Details with the stored pickup point and parcel plan. get_pickup_point() returns a Smart_Send\Delivery\Pickup_Point or null. See the pickup point accessors for the available fields.The helper reads the saved point; it does not find nearby points or refresh its address. If no Smart Send point is stored, it also recognizes the supported vConnect pickup point metadata. An agent number stored on its own does not provide a complete pickup point object. Individual fields can be null.get_parcel_plan() on the same details object returns the saved plan or null. To distinguish a missing plan from an invalid saved allocation, use SS_SHIPPING_WC()->order_meta()->parcel_plan_error($order), which returns an explanation or null. These stored details do not resolve a shipping method; use the next example for that.Read shipping methods and booking defaults
Read shipping methods and booking defaults
- Description
- Example
$order->get_shipping_methods()returns the WooCommerce shipping line items saved on the order.get_method_id()identifies the WooCommerce method, such assmart_send_shippingorfree_shipping;get_instance_id()identifies the shipping-zone method instance.SS_SHIPPING_WC()->method_resolver()resolves one Smart Send service ID for each direction, such aspostnord_agentorpostnord_returndropoff. It reads the order’s Smart Send shipping-line metadata, the current mapping for native free shipping, or supported third-party method mappings.
resolve_outbound($order) and resolve_return($order) return '' when no service can be resolved. If a Smart Send shipping line has no return method configured, resolve_return() throws Smart_Send\Booking\Exceptions\Booking_Exception; the example keeps this distinction in return_error. is_auto_return_enabled($order) reads the automatic-return setting saved on the shipping line.These are the defaults derived for the order. They do not include unsaved choices in the order screen, submitted booking overrides, or changes made by smart_send_delivery_details. They also do not tell you which service a previous shipment was actually booked with; read that from the Booked_Shipment delivered to a booking action.Read saved bookings
Read saved bookings
- Description
- Example
SS_SHIPPING_WC()->shipment_ids() reads the shipment references saved on the order:direction is outbound or return; booked_at is an ISO 8601 UTC timestamp or null when unavailable. The plugin retains the latest 50 history rows in total across both directions. The latest ID for each direction is stored separately, so an ID can exist even when labels() is empty. A row represents one shipment, which may contain several parcels.These are saved booking references. They do not contain live carrier status, tracking links, documents or the complete Booked_Shipment. To read documents and tracking details returned by a booking, listen to smart_send_booking_completed or smart_send_order_fulfilled and use the booked result accessors. A Fulfillment_Result describes that particular run, including a possible outbound success and return failure; it is not re-created from the order history.Pickup-point accessors
Pickup-point accessors
Pickup_Point supplies get_agent_no(), get_company(), get_address_line1(), get_address_line2(), get_postal_code(), get_city(), get_country(), get_carrier(), get_distance(), get_latitude(), get_longitude() and get_opening_hours(). Optional values can be null. Opening hours are a list of day, opens, closes rows: the day is a lowercase English weekday and times use HH:MM:SS. An empty list means unknown opening hours. to_array() gives a serializable representation; it is not permission to trust client-submitted names or addresses.Read booked results
Read booked results
Booked_Shipment exposes get_shipment_id(), get_carrier(), get_service_code(), is_return(), get_state(), get_booked_at(), get_tracking_code(), get_tracking_url(), parcels(), documents() and codes(). Optional tracking fields can be null. label_document() returns a Shipment_Document or null; do not assume a PDF exists for every result. A document’s download_url() chooses the saved local copy when available, otherwise the Smart Send URL.Fulfillment_Result::get_steps($shipment) reports save_documents (true, false or 'failed'), order_note (boolean), tracking (whether forwarding was requested) and order_status (status or false). A tracking step does not prove that an optional third-party integration was installed or delivered an email.Use get_order_note_id($shipment) for the saved note’s integer ID or null. get_order_note($shipment) supplies note HTML for PHP consumers. The serializable to_array() instead contains an order_note object with an id, not note HTML. Its rows have direction, status (fulfilled/failed), and shipment/steps/warnings or an error. get_error_details($is_return) returns null or an array with message, response_id, fields and html; treat message as plain text and escape output appropriately.