> ## Documentation Index
> Fetch the complete documentation index at: https://docs.smartsend.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Developer reference

> Smart Send-plugin'ets hooks, metafelter og API til tilpasninger og læsning af forsendelses- og bookingoplysninger på WooCommerce-ordrer.

Tilpas Smart Send-plugin'et med WordPress-filtre og actions i din egen webshop. Hooks lader dig ændre checkout, forsendelsesvalg og bookingforløbet uden at redigere pluginets kode. Brug [metafeltreferencen](#metadata) til at forstå gemte værdier og [API’et](#api) til at hente afhentningssteder, fragtmetoder og bookinger for en WooCommerce-ordre.

## Filtre og actions

<span id="vaelg-det-rigtige-trin" />

Vælg det trin, som passer til din tilpasning. Hvert trin og hook nedenfor linker til den detaljerede beskrivelse og et eksempel.

| Trin                                                                          | Formål                                                                                | Relevante hooks og filtre                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [Tilgængelighed og priser i checkout](#tilgaengelighed-og-priser-i-checkout)  | Styr tilgængelighed, gratis fragt og ekstra fragtpriser.                              | [`woocommerce_shipping_smart_send_shipping_is_available`](#woocommerce-shipping-smart-send-shipping-is-available), [`woocommerce_shipping_smart_send_shipping_is_free_shipping`](#woocommerce-shipping-smart-send-shipping-is-free-shipping), [`woocommerce_smart_send_shipping_shipping_add_rate`](#woocommerce-smart-send-shipping-shipping-add-rate)                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| [Afhentningssteder](#afhentningssteder)                                       | Tilpas opslag, sortering, tekster og timeout for afhentningssteder.                   | [`smart_send_pickup_point_search_params`](#smart-send-pickup-point-search-params), [`smart_send_pickup_point_list`](#smart-send-pickup-point-list), [`smart_send_pickup_point_label`](#smart-send-pickup-point-label), [`smart_send_pickup_point_timeout`](#smart-send-pickup-point-timeout)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| [Shipping label booking](#shipping-label-booking)                             | Styr fragtmetoder, kollifordeling og vægt, ordredata, bookingforespørgsler og events. | [`smart_send_fulfillment_shipping_methods`](#smart-send-fulfillment-shipping-methods), [`smart_send_delivery_details`](#smart-send-delivery-details), [`smart_send_parcel_default_weight`](#smart-send-parcel-default-weight), [`smart_send_order_receiver`](#smart-send-order-receiver), [`smart_send_receiver_phone`](#smart-send-receiver-phone), [`smart_send_payload_receiver`](#smart-send-payload-receiver), [`smart_send_payload_items`](#smart-send-payload-items), [`smart_send_payload_totals`](#smart-send-payload-totals), [`smart_send_shipment_freetext`](#smart-send-shipment-freetext), [`smart_send_booking_request`](#smart-send-booking-request), [`smart_send_booking_completed`](#smart-send-booking-completed), [`smart_send_booking_failed`](#smart-send-booking-failed) |
| [Ordreopdateringer og samlet resultat](#ordreopdateringer-og-samlet-resultat) | Styr dokumenter, ordrenoter, tracking og status, og læs det samlede resultat.         | [`smart_send_fulfillment_save_documents`](#smart-send-fulfillment-save-documents), [`smart_send_fulfillment_order_note`](#smart-send-fulfillment-order-note), [`smart_send_fulfillment_tracking`](#smart-send-fulfillment-tracking), [`smart_send_fulfillment_order_status`](#smart-send-fulfillment-order-status), [`smart_send_order_fulfilled`](#smart-send-order-fulfilled)                                                                                                                                                                                                                                                                                                                                                                                                                  |
| [Plugin settings](#plugin-settings)                                           | Tilpas API-forbindelse, logning, links og pluginets opdateringsbesked.                | [`smart_send_api_endpoint`](#smart-send-api-endpoint), [`smart_send_sslverify`](#smart-send-sslverify), [`smart_send_logging`](#smart-send-logging), [`smart_send_configuration_url`](#smart-send-configuration-url), [`smart_send_support_url`](#smart-send-support-url), [`ss_in_plugin_update_message`](#ss-in-plugin-update-message)                                                                                                                                                                                                                                                                                                                                                                                                                                                         |

WooCommerces og Subscriptions’ integrationspunkter er samlet i [integrationsreferencen](#integrationsreference).

`$is_return` er `false` for udgående fragt og `true` for returfragt i de signaturer, hvor argumentet findes. En samlet booking kan kalde samme callback to gange, én gang pr. retning. Events med et `Booked_Shipment`-objekt giver i stedet adgang til `$shipment->is_return()`.

<Note>
  `smart_send_booking_completed` betyder, at Smart Send har oprettet én forsendelse. Det kører, før pluginet gemmer bookingoplysningerne på WooCommerce-ordren. Brug `smart_send_order_fulfilled`, når du skal bruge det samlede resultat af ordreopdateringerne, også når udgående fragt lykkes, men returfragt fejler.
</Note>

Signaturer angiver filterværdien først og derefter kontekstargumenter; `→` angiver den krævede returtype. Actions har ingen brugbar returværdi. Eksemplerne er selvstændige tilpasninger, ikke en fil, der skal installeres samlet.

Åbn det relevante hook, og vælg **Beskrivelse** for kontrakten eller **Eksempel** for PHP-koden og vejledningen til brug.

<span id="tilgaengelighed-og-priser-i-checkout" />

### Tilgængelighed og priser i checkout

<AccordionGroup>
  <Accordion title="woocommerce_shipping_smart_send_shipping_is_available" id="woocommerce-shipping-smart-send-shipping-is-available">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(bool $is_available, array $package, Smart_Send\Shipping_Method\Method $method) → bool`

        Kører efter metodens kontrol af fragtklasser og kunderoller. Returnér `false` for at skjule denne Smart Send-instans for pakken; returnér den modtagne værdi for at bevare eksisterende begrænsninger. `true` opretter ikke en pris uden for vægttabellen. Gælder checkout; foretager ingen booking eller ordreopdatering. Eksemplet begrænser desuden metoden til Danmark.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'woocommerce_shipping_smart_send_shipping_is_available', function ( bool $available, array $package, \Smart_Send\Shipping_Method\Method $method ): bool {
        	return $available && 'DK' === ( $package['destination']['country'] ?? '' );
        }, 10, 3 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="woocommerce_shipping_smart_send_shipping_is_free_shipping" id="woocommerce-shipping-smart-send-shipping-is-free-shipping">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(bool $is_free, array $package, Smart_Send\Shipping_Method\Method $method) → bool`

        Kører efter kontrol af minimumsbeløb/kupon, når kurvens vægt er tilladt. `true` vælger **Flat fee cost**, som ikke nødvendigvis er nul; `false` bruger normal vægtprisberegning. Det tilsidesætter ikke tilgængelighed ud fra zone, rolle, klasse eller vægt. Eksemplet deaktiverer fastprisgrenen og bevarer den normale prisberegning.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'woocommerce_shipping_smart_send_shipping_is_free_shipping', '__return_false' );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="woocommerce_smart_send_shipping_shipping_add_rate" id="woocommerce-smart-send-shipping-shipping-add-rate">
    <Tabs>
      <Tab title="Beskrivelse">
        **Action** · `(Smart_Send\Shipping_Method\Method $method, array $rate) → void`

        Kører ved afslutningen af en Smart Send-prisberegning. `$rate` indeholder `id`, `label`, `cost`, `meta_data` og `package`. Det kan køre, selv om vægtreglerne ikke gav en fragtpris, så kontrollér `$method->rates`, før du opretter et ekstra valg. Eksemplet lægger 10 i shoppens valuta til en eksisterende pris før WooCommerces momsberegning. Den oprindelige services metadata bevares; eksemplet booker ikke en anden transportørservice.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_action( 'woocommerce_smart_send_shipping_shipping_add_rate', function ( \Smart_Send\Shipping_Method\Method $method, array $rate ): void {
        	if ( ! isset( $method->rates[ $rate['id'] ] ) ) {
        		return;
        	}
        	$rate['cost']  = (float) $method->rates[ $rate['id'] ]->get_cost() + 10;
        	$rate['id']   .= ':extra-handling';
        	$rate['label'] = 'Levering med ekstra håndtering';
        	$method->add_rate( $rate );
        }, 10, 2 );
        ```
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

### Afhentningssteder

<AccordionGroup>
  <Accordion title="smart_send_pickup_point_search_params" id="smart-send-pickup-point-search-params">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(array $params) → array`

        Kører før API-opslag efter nærmeste afhentningssteder, når en API-nøgle er konfigureret. Nøgler: `carrier`, `country`, `postal_code`, `street` (strenge) og `city` (streng eller null). Returnér alle nøgler. API'et bestemmer antal resultater; begræns listen med `smart_send_pickup_point_list`. Søgeparametre ændrer ikke kundens ordreadresse. Eksemplet fjerner indledende/afsluttende mellemrum i postnummeret.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_pickup_point_search_params', function ( array $params ): array {
        	$params['postal_code'] = trim( $params['postal_code'] );
        	return $params;
        } );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_pickup_point_list" id="smart-send-pickup-point-list">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(Smart_Send\Delivery\Pickup_Point[] $points, array $params) → Smart_Send\Delivery\Pickup_Point[]`

        Kører efter et ikke-tomt API-resultat er konverteret til `Pickup_Point`-objekter, før caching i sessionen og visning. Returnér en liste med fortløbende indeks og kompatible objekter. Pluginet fjerner objekter, der ikke matcher opslagets transportør/land. Filteret kaldes ikke ved et tomt API-resultat. Sorteringen påvirker **Autovælg**, når kunden ikke allerede har et kompatibelt eksplicit valg; filteret kan ikke bruges til at tilbagekalde et sådant valg.
      </Tab>

      <Tab title="Eksempel">
        Eksemplet placerer steder med et åbningstidsinterval om lørdagen først, bevarer den eksisterende afstandssortering inden for hver gruppe og viser højst fem steder. Det opfinder eller ændrer ikke adresser. En ukendt liste over åbningstider behandles som manglende viden om lørdagsåbning.

        ```php theme={null}
        add_filter( 'smart_send_pickup_point_list', function ( array $points, array $params ): array {
        	$saturday = array();
        	$other    = array();
        	foreach ( $points as $point ) {
        		$open_saturday = false;
        		foreach ( $point->get_opening_hours() as $interval ) {
        			if ( 'saturday' === $interval['day'] ) {
        				$open_saturday = true;
        				break;
        			}
        		}
        		if ( $open_saturday ) {
        			$saturday[] = $point;
        		} else {
        			$other[] = $point;
        		}
        	}
        	return array_slice( array_merge( $saturday, $other ), 0, 5 );
        }, 10, 2 );
        ```

        **Forventet resultat:** for steder i afstandsrækkefølge A (mandag), B (lørdag), C (lørdag), D (ukendt) bliver rækkefølgen B, C, A, D. Med **Autovælg** aktiveret og uden et eksplicit valg bliver B standardvalget. Et kompatibelt sted, kunden selv har valgt, forbliver valgt, selv om det ligger uden for de nye fem første. Filteret ændrer de tilbudte kandidater, ikke gyldigheden af kundens valg. Test med en opdateret adresse, da resultater kan være gemt i checkoutsessionen.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_pickup_point_label" id="smart-send-pickup-point-label">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $label, Smart_Send\Delivery\Pickup_Point $point) → string`

        Kører ved formatering af et afhentningssteds tekst efter **Dropdown-format**. Returnér almindelig tekst, ikke HTML eller allerede escapede entities. Hver visning escaper selv teksten. Filteret ændrer visningen, ikke afhentningsstedets identitet eller gemte adresse. Identiteten består af det præcise agentnummer sammen med transportør og land.
      </Tab>

      <Tab title="Eksempel">
        Tilføj agentnummeret til den eksisterende tekst i både klassisk checkout og checkoutblokken. Returnér almindelig tekst, som ikke allerede er escaped: et og-tegn i virksomhedsnavnet skal forblive `&`, ikke `&amp;`. Visningen håndterer escaping. Det gemte afhentningssted ændres ikke.

        ```php theme={null}
        add_filter( 'smart_send_pickup_point_label', function ( string $label, \Smart_Send\Delivery\Pickup_Point $point ): string {
        	return $label . ' (#' . $point->get_agent_no() . ')';
        }, 10, 2 );
        ```

        **Forventet resultat:** `Hjørnebutik & Kiosk (#00123)`. Indledende nuller i agentnummeret bevares. Kontrollér begge checkouttyper og det valgte sted på ordren.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_pickup_point_timeout" id="smart-send-pickup-point-timeout">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(int $seconds) → int|float`

        Standard: 4 sekunder. Kører ved både opslag efter nærmeste steder og opslag på ét sted. Returnér en positiv timeout i sekunder. En højere værdi kan forlænge ventetiden i checkout; den garanterer ikke resultater. Eksemplet tillader seks sekunder.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_pickup_point_timeout', function ( int $seconds ): int {
        	return 6;
        } );
        ```
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

### Shipping label booking

Tilpas ordresidens fragtmetoder, forsendelsesvalg, kollifordeling og kollivægt samt modtager- og ordredata. Hooks nedenfor følger bookingforløbet frem til bookingforespørgslen og events for vellykket eller fejlet booking. Brug [`smart_send_delivery_details`](#smart-send-delivery-details) til at ændre varefordelingen og [`smart_send_parcel_default_weight`](#smart-send-parcel-default-weight) til at tilpasse den beregnede kollivægt ved booking.

<AccordionGroup>
  <Accordion title="smart_send_fulfillment_shipping_methods" id="smart-send-fulfillment-shipping-methods">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(array $carriers, WC_Order $order, bool $is_return) → array`

        Kører separat for listen over udgående services og returservices på ordresiden. Hver transportør har `code`, `name`, `services`; hver service har `code`, `name`, `addons` (aktuelt et tomt array). En bookingmetode er `carrier_service`, eksempelvis `postnord_agent`. Returnér den filtrerede transportørliste. Den valgte metode tilføjes altid igen, hvis den mangler, også når du returnerer `[]`. Filteret begrænser UI'et; det er ikke adgangskontrol. Håndhæv bookingregler i `smart_send_delivery_details`. Eksemplet tilbyder kun PostNord til udgående fragt, med forbehold for den valgte metode.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_fulfillment_shipping_methods', function ( array $carriers, \WC_Order $order, bool $is_return ): array {
        	if ( $is_return ) {
        		return $carriers;
        	}
        	return array_values( array_filter( $carriers, function ( array $carrier ): bool {
        		return 'postnord' === $carrier['code'];
        	} ) );
        }, 10, 3 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_delivery_details" id="smart-send-delivery-details">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(Smart_Send\Delivery\Delivery_Details $details, WC_Order $order, bool $is_return) → Smart_Send\Delivery\Delivery_Details`

        Kører én gang pr. forsøgt retning, efter gemt opsætning, fundet service og indsendte ændringer er flettet sammen, før validering af afhentningssted og booking. Returnér details-objektet. Brug `set_shipping_method()`, `set_pickup_point()` eller `set_parcel_plan()`; brug `clear_pickup_point()` til en eksplicit rydning i et delvist details-objekt. Kast `Smart_Send\Booking\Exceptions\Booking_Exception` for at afvise en forretningsregel før booking. Filterændringer gælder den aktuelle booking; de gemmes ikke automatisk. Se [forsendelsesvalg og lagring](#delivery-details-and-persistence).
      </Tab>

      <Tab title="Eksempel">
        Dette afgrænsede eksempel opdeler en udgående ordre med præcis én linje og tre hele enheder i to kolli: 2 + 1. Returbookinger og eksisterende eller indsendte kolliplaner bevares. Tilpas udvælgelsesreglen til dine faktiske produkter og din pakkeproces, før du aktiverer den.

        ID'erne i `add_item()` er **WooCommerce-ordrelinje-ID'er**, ikke produkt- eller variations-ID'er. Målene nedenfor er i cm. Vægten forbliver automatisk, så [eksemplet med emballagevægt](#smart-send-parcel-default-weight) kan gælde for hvert kolli.

        ```php theme={null}
        add_filter( 'smart_send_delivery_details', function ( \Smart_Send\Delivery\Delivery_Details $details, \WC_Order $order, bool $is_return ): \Smart_Send\Delivery\Delivery_Details {
        	if ( $is_return || null !== $details->get_parcel_plan() ) {
        		return $details;
        	}
        	$items = array_values( $order->get_items() );
        	if ( 1 !== count( $items ) || 3.0 !== (float) $items[0]->get_quantity() ) {
        		return $details;
        	}
        	$item  = $items[0];
        	$first = new \Smart_Send\Delivery\Parcel_Spec();
        	$first->add_item( $item->get_id(), 2, $item->get_name() )
        		->set_length( 30 )->set_width( 20 )->set_height( 15 );
        	$second = new \Smart_Send\Delivery\Parcel_Spec();
        	$second->add_item( $item->get_id(), 1, $item->get_name() )
        		->set_length( 30 )->set_width( 20 )->set_height( 10 );
        	$plan = new \Smart_Send\Delivery\Parcel_Plan();
        	$plan->add_spec( $first )->add_spec( $second );
        	return $details->set_parcel_plan( $plan );
        }, 10, 3 );
        ```

        **Forventet resultat:** en ordrelinje med ID 701 og antal 3 bliver til fordelingerne `(701, 2)` og `(701, 1)`. Alle tre enheder fordeles én gang. For en vare på 0,50 kg og 0,20 kg emballage pr. kolli bliver vægtene 1,20 kg og 0,70 kg. Manglende produktvægt skal stadig rettes eller erstattes med en eksplicit kollivægt. Planen styrer denne booking; filterets resultat gemmes ikke automatisk som ordrens kolliopsætning. Se brugerforløbet under [Kolli-forsendelser](/da/integrations/woocommerce/shipping-labels#colli-shipments).
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_parcel_default_weight" id="smart-send-parcel-default-weight">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(float $weight, Smart_Send\Delivery\Parcel_Spec $spec, WC_Order $order) → float`

        Kører **ved booking** for hvert kolli uden eksplicit vægt. Input er den samlede produktvægt for de varer og antal, der er fordelt til kolliet, i **kg**, eventuelt nul. Filteret ændrer bookingens kollivægt; det ændrer hverken varefordelingen, den beregnede vægt vist på ordresiden eller den gemte kolliplan. Returnér en endelig, brugbar vægt inklusive emballage. Eksplicit vægt via `Parcel_Spec::set_weight()` eller ordresiden springer filteret over. Et fordelt, slettet produkt med ukendt vægt giver valideringsfejl før filteret; angiv i stedet en eksplicit positiv kollivægt. Der er intet retningsargument; filteret kan køre for både udgående og retur.
      </Tab>

      <Tab title="Eksempel">
        Læg 0,20 kg emballage til hvert kolli, hvis vægt beregnes ud fra varerne. Filteret bruger kg uanset shoppens vægtenhed i produktkataloget. Det kan køre for både udgående kolli og returkolli.

        ```php theme={null}
        add_filter( 'smart_send_parcel_default_weight', function ( float $weight, \Smart_Send\Delivery\Parcel_Spec $spec, \WC_Order $order ): float {
        	return $weight + 0.20;
        }, 10, 3 );
        ```

        **Forventet resultat:** varer på i alt 1,50 kg bookes med en kollivægt på 1,70 kg. Ordresidens beregnede visning er fortsat 1,50 kg. En eksplicit indtastet kollivægt på 2,00 kg forbliver 2,00 kg; den repræsenterer allerede totalen inklusive emballage. Et slettet produkt med ukendt vægt kræver stadig en eksplicit positiv kollivægt. Filteret ændrer ikke checkoutpriser ud fra vægtintervaller eller gemte produktvægte.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_order_receiver" id="smart-send-order-receiver">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(array $shipping_address, int $order_id) → array`

        Kører ved læsning af ordrens leveringsadresse før fallback for telefon/e-mail og konvertering til modtagerdata. Bruger WooCommerce-adressenøgler som `first_name`, `last_name`, `company`, `address_1`, `address_2`, `postcode`, `city`, `country` og eventuelt `phone`/`email`. Returnér hele adressen. Andet argument er ordre-ID, ikke et `WC_Order`. Begge retninger bruger samme læsetrin; filteret gemmer ikke adressen.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_order_receiver', function ( array $address, int $order_id ): array {
        	$address['country'] = strtoupper( $address['country'] );
        	return $address;
        }, 10, 2 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_receiver_phone" id="smart-send-receiver-phone">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string|null $phone, WC_Order $order) → string|null`

        Kører efter valg af leveringstelefon eller faktureringstelefon, når leverings- og faktureringsland matcher, og efter fjernelse af omgivende mellemrum. Returnér et telefonnummer eller `null`. Der sendes intet retningsflag. Eksemplet fjerner mellemrum uden at gætte en landekode.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_receiver_phone', function ( ?string $phone, \WC_Order $order ): ?string {
        	return null === $phone ? null : preg_replace( '/\s+/', '', $phone );
        }, 10, 2 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_payload_receiver" id="smart-send-payload-receiver">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(array $receiver, WC_Order $order) → array`

        Kører efter mapping af modtageren og fallback for telefon/e-mail. Nøgler: `company`, `name_line1`, `name_line2`, `address_line1`, `address_line2`, `postal_code`, `city`, `country` (strenge), `phone` og `email` (streng eller null). Returnér alle nøgler. Dette er pluginets data, ikke et råt HTTP-payload, og de bruges i begge retninger. Eksemplet fjerner utilsigtede mellemrum omkring en e-mail, der ikke er null.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_payload_receiver', function ( array $receiver, \WC_Order $order ): array {
        	if ( null !== $receiver['email'] ) {
        		$receiver['email'] = trim( $receiver['email'] );
        	}
        	return $receiver;
        }, 10, 2 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_payload_items" id="smart-send-payload-items">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(array[] $items, WC_Order $order) → array[]`

        Kører efter læsning af én række pr. ordrelinje, før fordeling på kolli, i begge retninger. Bevar identiteter og gyldige antal; brug `smart_send_delivery_details` til fordelingen. Se [strukturen for varerækker](#item-rows). Netto/moms er **linjetotaler** efter rabat, ikke stykpriser. Eksemplet fjerner mellemrum omkring toldbeskrivelsen uden at opfinde en beskrivelse for et slettet produkt.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_payload_items', function ( array $items, \WC_Order $order ): array {
        	foreach ( $items as &$item ) {
        		if ( is_string( $item['description'] ) ) {
        			$item['description'] = trim( $item['description'] );
        		}
        	}
        	unset( $item );
        	return $items;
        }, 10, 2 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_payload_totals" id="smart-send-payload-totals">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(array $totals, WC_Order $order) → array`

        Kører efter beregning af ordretotaler og begrænsning af negative netto-/momsbeløb til nul. Returnér alle nøgler i [skemaet for totaler](#totals). Senere værdier bruges som returneret; bevar sammenhængen og ikke-negative beløb. Ordregebyrer indgår i forsendelsestotaler, mens kollitotaler indeholder fordelte varer. Eksemplet logger kun valuta og ordretotal og bevarer bookingværdierne.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_payload_totals', function ( array $totals, \WC_Order $order ): array {
        	wc_get_logger()->info( 'Bookingværdi', array(
        		'source'   => 'my-shop-shipping',
        		'currency' => $totals['currency'],
        		'total'    => $totals['total_net_amount'] + $totals['total_tax_amount'],
        	) );
        	return $totals;
        }, 10, 2 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_shipment_freetext" id="smart-send-shipment-freetext">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string|null $freetext, WC_Order $order) → string|null`

        Kører ved læsning af tekst til labelen i begge retninger. Input er kundens ordrekommentar, når **Påsæt ordrekommentar på pakkelabel** er aktiveret, ellers `null`. Returnér tekst eller `null`, ikke HTML. Dette styrer ikke WooCommerces ordrehistorik. Eksemplet udelader kundekommentarer på labels.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_shipment_freetext', '__return_null' );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_booking_request" id="smart-send-booking-request">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(Smart_Send\Booking\Shipment $shipment, WC_Order $order, bool $is_return) → Smart_Send\Booking\Shipment`

        Kører efter dataudtræk og opbygning af kolli, umiddelbart før oversættelse til API-forespørgslen. Returnér et `Shipment`. Brug tidligere filtre til fordelings-/vægtregler, da kollivalideringen allerede er udført her. Eksemplet tilføjer kun en intern reference til udgående fragt; det opdaterer ikke ordren eller gemmer fragtindstillinger.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_booking_request', function ( \Smart_Send\Booking\Shipment $shipment, \WC_Order $order, bool $is_return ): \Smart_Send\Booking\Shipment {
        	if ( ! $is_return ) {
        		$shipment->set_internal_reference( 'WEB-' . $order->get_order_number() );
        	}
        	return $shipment;
        }, 10, 3 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_booking_completed" id="smart-send-booking-completed">
    <Tabs>
      <Tab title="Beskrivelse">
        **Action** · `(Smart_Send\Booking\Booked_Shipment $booked, Smart_Send\Booking\Shipment $request, WC_Order $order) → void`

        Kører én gang pr. vellykket booket retning efter mapping af API-svaret og før lagring på ordren eller kopiering af dokumenter. Brug `$booked->is_return()` til retningen. Eventet betyder ikke, at hele udgående/retur-forløbet lykkedes, og en lokal dokumentkopi er endnu ikke klar. Kast ikke en exception fra callbacken: forsendelsen er allerede oprettet. Brug `smart_send_order_fulfilled`, når du skal bruge de gemte ordreresultater.
      </Tab>

      <Tab title="Eksempel">
        Registrér forsendelsens identitet og retning uden at basere dig på ordredata, der endnu ikke er gemt. Callbacken kører separat for udgående og retur, også når udgående fragt lykkes, og retur senere fejler.

        ```php theme={null}
        add_action( 'smart_send_booking_completed', function ( \Smart_Send\Booking\Booked_Shipment $booked, \Smart_Send\Booking\Shipment $request, \WC_Order $order ): void {
        	wc_get_logger()->info( 'Smart Send-forsendelse booket', array(
        		'source'      => 'my-shop-shipping',
        		'order_id'    => $order->get_id(),
        		'shipment_id' => $booked->get_shipment_id(),
        		'direction'   => $booked->is_return() ? 'return' : 'outbound',
        	) );
        }, 10, 3 );
        ```

        **Forventet resultat:** én post pr. oprettet forsendelse i WooCommerce-loggen under `my-shop-shipping`. En afvist booking giver ingen post. Eksemplet opretter ikke endnu en forsendelse, gemmer ikke en ordrenote og sender ikke kundemeddelelser. Brug forsendelses-ID som idempotensnøgle i en ekstern integration, og håndtér leveringsfejl uden at kaste en exception fra callbacken.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_booking_failed" id="smart-send-booking-failed">
    <Tabs>
      <Tab title="Beskrivelse">
        **Action** · `(Smart_Send\Booking\Exceptions\Booking_Exception $exception, Smart_Send\Booking\Shipment $request, WC_Order $order) → void`

        Kører, når bookingens API-kald kaster en håndteret HTTP-klientfejl, lige før den kastes videre som `Booking_Exception`. Læs `getMessage()`, `errors()` (felt → beskedliste) og `response_id()` (streng eller null). Det er ikke et event for alle fejl: lokal validering af fordeling, afhentningssted eller forsendelsesvalg kan fejle før API-kaldet. Der sendes ingen boolean for retningen. Eksemplet logger et response ID uden adressedata eller feltværdier.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_action( 'smart_send_booking_failed', function ( \Smart_Send\Booking\Exceptions\Booking_Exception $error, \Smart_Send\Booking\Shipment $request, \WC_Order $order ): void {
        	wc_get_logger()->warning( 'Smart Send-booking fejlede', array(
        		'source'      => 'my-shop-shipping',
        		'order_id'    => $order->get_id(),
        		'response_id' => $error->response_id(),
        	) );
        }, 10, 3 );
        ```
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

### Ordreopdateringer og samlet resultat

<AccordionGroup>
  <Accordion title="smart_send_fulfillment_save_documents" id="smart-send-fulfillment-save-documents">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(bool $save, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → bool`

        Kører efter vellykket booking og lagring af indsendte fragtændringer, før forsøg på dokumentkopiering og lagring af forsendelseshistorik. Standard er indstillingen **Gem kopi af PDF** i begge retninger. Returnér `false` for at springe lokale kopier over. En kopifejl giver en advarsel; forsendelsen forbliver booket, og dokumentlinks bruger Smart Send. Eksemplet lader dokumenterne blive hos Smart Send.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_fulfillment_save_documents', '__return_false' );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_fulfillment_order_note" id="smart-send-fulfillment-order-note">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $note_html, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → string`

        Kører efter lagring af forsendelseshistorik, før den normale ordrenote tilføjes. Returnér sikker HTML/tekst eller `''` for at udelade noten. Noter gemmes med `WC_Order::add_order_note()`, når kaldet anmoder om en note. WooCommerces historik opdateres efter genindlæsning; Smart Sends resultat kan vises med det samme. Eksemplet skriver en kort tekstnote for begge retninger.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_fulfillment_order_note', function ( string $note, \Smart_Send\Booking\Booked_Shipment $shipment, \WC_Order $order ): string {
        	return esc_html( 'Smart Send-forsendelse ' . $shipment->get_shipment_id() );
        }, 10, 3 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_fulfillment_tracking" id="smart-send-fulfillment-tracking">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(bool $push, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → bool`

        Kører efter ordrenotetrinnet, før tracking pr. kolli videresendes til det valgfrie WooCommerce Shipment Tracking-plugin. Standard: `true` udgående, `false` retur. Det opretter ikke live trackingopdateringer og installerer ikke pluginet. `false` bevarer den bookede forsendelses egne trackingdata. Eksemplet deaktiverer videresendelse.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_fulfillment_tracking', '__return_false' );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_fulfillment_order_status" id="smart-send-fulfillment-order-status">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string|false $status, Smart_Send\Booking\Booked_Shipment $shipment, WC_Order $order) → string|false`

        Kører efter tracking. Returnér en registreret WooCommerce-status som `wc-completed` eller `false` for at bevare ordren uændret. Standard: konfigureret **Ændre ordrens status efter labelgenerering** for udgående; `false` for retur. En statusændring kan udløse WooCommerce-/tredjepartshooks og e-mails. Eksemplet forhindrer Smart Send i at ændre status i begge retninger.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_fulfillment_order_status', '__return_false' );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_order_fulfilled" id="smart-send-order-fulfilled">
    <Tabs>
      <Tab title="Beskrivelse">
        **Action** · `(WC_Order $order, Smart_Send\Fulfillment\Fulfillment_Result $result) → void`

        Kører én gang efter alle forsøgte retninger og deres ordreopdateringer, når mindst én retning lykkedes. Det kører ikke ved et fuldstændigt mislykket forløb. Resultatet kan indeholde en vellykket udgående forsendelse og en fejlet retur. Undersøg `get_outbound_shipment()`, `get_return_shipment()`, `shipments()`, `get_steps($shipment)`, `get_order_note_id($shipment)` og `get_warnings($shipment)`. `get_validation_errors($is_return)` og `get_error_details($is_return)` beskriver fejl. Se [kontrakterne for bookingresultater](#read-booked-results); antag ikke, at alle valgfrie trin blev udført.
      </Tab>

      <Tab title="Eksempel">
        Brug dette event, når du skal bruge gemte note-ID'er, endelige dokument-URL'er eller resultatet for begge retninger. Eksemplet registrerer vellykkede forsendelser og markerer separat en fejlet retur. Det antager ikke, at alle valgfrie ordreopdateringer var aktiveret.

        ```php theme={null}
        add_action( 'smart_send_order_fulfilled', function ( \WC_Order $order, \Smart_Send\Fulfillment\Fulfillment_Result $result ): void {
        	foreach ( $result->shipments() as $shipment ) {
        		$label = $shipment->label_document();
        		wc_get_logger()->info( 'Smart Send-ordre opdateret', array(
        			'source'        => 'my-shop-shipping',
        			'order_id'      => $order->get_id(),
        			'shipment_id'   => $shipment->get_shipment_id(),
        			'note_id'       => $result->get_order_note_id( $shipment ),
        			'has_document'  => null !== $label,
        			'warning_count' => count( $result->get_warnings( $shipment ) ),
        		) );
        	}
        	if ( null !== $result->get_return_error() ) {
        		wc_get_logger()->warning( 'Returbooking kræver opmærksomhed', array(
        			'source'   => 'my-shop-shipping',
        			'order_id' => $order->get_id(),
        		) );
        	}
        }, 10, 2 );
        ```

        **Forventet resultat:** en vellykket samlet booking logger to forsendelser. Vellykket udgående fragt med fejlet retur logger den udgående forsendelse og én advarsel; gentag kun den fejlede retning. Hvis en lokal PDF-kopi fejler, står forsendelsen stadig på listen, og `warning_count` stiger. Læs `$label->download_url()` i din egen integration, når du har kontrolleret, at `$label` ikke er null. Log ikke private dokument-URL'er. Eventet kører ikke, når alle forsøgte retninger fejler.
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

### Plugin settings

<AccordionGroup>
  <Accordion title="smart_send_api_endpoint" id="smart-send-api-endpoint">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $host) → string`

        Kører ved oprettelse af API-klienten. Standardhost: `https://app.smartsend.io`. Returnér kun protokol og hostname, eksempelvis `https://app.smartsend.dev`; klienten tilføjer selv API-versionsstien. Gælder autentificering, opslag af afhentningssteder og booking. Brug adgangsoplysninger til det valgte miljø; en stagingshop ændrer ikke denne host i sig selv.
      </Tab>

      <Tab title="Eksempel">
        Brug en eksplicit udpeget testshop og adgangsoplysninger til Smart Sends sandbox. Bekræft den ønskede sandboxkonto og transportøropsætning før booking. Hostfilteret påvirker både validering af API-nøglen, opslag af afhentningssteder og booking.

        1. Sæt WordPress' `WP_ENVIRONMENT_TYPE` til `staging` i testshoppens konfiguration.
        2. Tilføj callbacken nedenfor i dit tilpasningsplugin.
        3. Indtast og gem API-nøglen til sandboxmiljøet, og validér den.
        4. Kontrollér checkout separat, og book derefter en fiktiv testordre i det konfigurerede miljø.

        Callbacken ændrer kun host for et stagingmiljø. Tilføj ikke `/api/v1/` eller en anden API-sti; klienten tilføjer den selv.

        ```php theme={null}
        add_filter( 'smart_send_api_endpoint', function ( string $host ): string {
        	if ( 'staging' !== wp_get_environment_type() ) {
        		return $host;
        	}
        	return 'https://app.smartsend.dev';
        } );
        ```

        **Forventet resultat:** stagingforespørgsler bruger `https://app.smartsend.dev` plus API-stien, klienten tilføjer; produktion bevarer den modtagne host. Bevar kontrol af TLS-certifikater. Fjern sandboxændringen, og konfigurér de ønskede produktionsoplysninger ved opsætning af en produktionsshop. Pluginets automatiske test-mocks er testfixtures, ikke en demoknap til shopbrugere.
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_sslverify" id="smart-send-sslverify">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(bool $verify) → bool`

        Standard: `true`. Kører ved opbygning af WordPress' HTTP-indstillinger. Bevar certifikatkontrol i både produktion og sandbox. Eksemplet fastholder eksplicit kontrollen; ret et ugyldigt servercertifikat eller CA-opsætningen frem for at slå kontrollen fra.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_sslverify', '__return_true' );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_logging" id="smart-send-logging">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $message, string $level, array $context) → string|null|false`

        Kører kun for logposter, som pluginets logningsregler tillader. `$level` er et WooCommerce-logniveau; `$context` indeholder `source` (`smart-send-logistics`) og pluginversion. Returnér en ændret besked eller `null`/`false` for at undertrykke posten. Filteret kan ikke aktivere fravalgte poster eller erstatte context ved at returnere et array. Eksemplet undertrykker kun debugbeskeder.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_logging', function ( string $message, string $level, array $context ) {
        	return 'debug' === $level ? null : $message;
        }, 10, 3 );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_configuration_url" id="smart-send-configuration-url">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $url) → string`

        Kører ved opbygning af Smart Send-rækkens opsætningslink på WordPress' pluginside. Standard: `https://smartsend.io/woocommerce/configuration/`. Returnér en URL, ikke HTML. Det ændrer ikke API-endpointet. Eksemplet sender linket til Smart Sends lokale indstillingsside.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_configuration_url', function ( string $url ): string {
        	return admin_url( 'admin.php?page=wc-settings&tab=shipping&section=smart_send_shipping' );
        } );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="smart_send_support_url" id="smart-send-support-url">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $url) → string`

        Kører for supportlinket på WordPress' pluginside. Standard: `https://smartsend.io/support/`. Returnér en URL; visningen escaper den. Eksemplet peger på en supportside i din egen shop; opret siden, før du bruger koden.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'smart_send_support_url', function ( string $url ): string {
        	return home_url( '/shipping-help/' );
        } );
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="ss_in_plugin_update_message" id="ss-in-plugin-update-message">
    <Tabs>
      <Tab title="Beskrivelse">
        **Filter** · `(string $notice_html) → string`

        Kører, når Smart Send viser en opdateringsbesked for en hovedversion på pluginsiden. Returnér betroet, sikker HTML: resultatet vises som HTML uden endnu en rensning. Eksemplet tilføjer statisk vejledning. Det er et hook til opdateringsbeskeder, ikke fragt eller booking.
      </Tab>

      <Tab title="Eksempel">
        ```php theme={null}
        add_filter( 'ss_in_plugin_update_message', function ( string $notice ): string {
        	return $notice . '<p>Gennemgå shoppens tilpasninger før opdatering.</p>';
        } );
        ```
      </Tab>
    </Tabs>
  </Accordion>
</AccordionGroup>

### Datakontrakter

De seks filtre til læsning af ordredata ovenfor modtager ikke et returflag. De læser samme ordredata i begge retninger. `smart_send_payload_totals` og `smart_send_shipment_freetext` kører kun, når varedata ikke er tomme. Brug `smart_send_booking_request` til en afsluttende ændring for en bestemt retning.

<AccordionGroup>
  <Accordion title="Varerækker" id="item-rows">
    `smart_send_payload_items` modtager disse nøgler på hver række:

    | Nøgler                                        | Type og betydning                                                               |
    | --------------------------------------------- | ------------------------------------------------------------------------------- |
    | `order_item_id`                               | Heltals-ID for WooCommerce-ordrelinjen; brug det til fordeling.                 |
    | `product_id`, `variation_id`                  | Heltalsreferencer til kataloget; de identificerer ikke en ordrelinje.           |
    | `sku`, `name`                                 | Strenge. Et manglende produkt har tomt SKU og det oversatte navn **Slettet**.   |
    | `description`, `hs_code`, `country_of_origin` | Produktets toldoplysninger som strenge eller null, når produktet ikke findes.   |
    | `quantity`                                    | Ordrelinjens antal; fordeling på kolli kræver positive hele antal.              |
    | `unit_weight`                                 | Float i kg eller null for et utilgængeligt produkt.                             |
    | `total_net_amount`, `total_tax_amount`        | Ikke-negative floats for hele linjen efter rabat.                               |
    | `product_missing`                             | Boolean, som angiver et utilgængeligt katalogprodukt/en utilgængelig variation. |
  </Accordion>

  <Accordion title="Totaler" id="totals">
    `smart_send_payload_totals` modtager floats `subtotal_net_amount`, `subtotal_tax_amount`, `shipping_net_amount`, `shipping_tax_amount`, `total_net_amount`, `total_tax_amount` samt strengen `currency`. Subtotalen udelader fragt og inkluderer øvrige ordregebyrer. Normalt gælder subtotal + fragt = total, separat for netto og moms; begrænsningen af negative beløb kan have forrang. Beløb inklusive moms er netto + moms. Bevar sammenhængene, når du ændrer totaler.
  </Accordion>
</AccordionGroup>

### Integrationsreference

Dette er baggrund om platformhooks, Smart Send bruger, ikke yderligere offentlige Smart Send-hooks til tilpasning.

<AccordionGroup>
  <Accordion title="WooCommerce-integrationspunkter" id="woocommerce-integration-points">
    De tre WooCommerce-navngivne checkout-hooks ovenfor er beregnet til tilpasninger. Tabellen nedenfor forklarer relevante platformhooks, som Smart Send **lytter til**. De overordnede kontrakter tilhører WooCommerce; at erstatte Smart Sends callbacks er ikke den understøttede tilpasningsvej.

    | Platformhook og argumenter                                                                                                 | Smart Sends anvendelse                                                                                                                                               |
    | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `woocommerce_shipping_methods` — filter `(array $methods)`                                                                 | Registrerer Smart Send-fragtmetoden; returnerer metoderegistret.                                                                                                     |
    | `woocommerce_package_rates` — filter `(WC_Shipping_Rate[] $rates, array $package)`                                         | Sorterer beregnede fragtpriser, når det er konfigureret; returnerer prisobjekter med rate-ID som nøgle. Brug en senere prioritet til din egen afsluttende sortering. |
    | `woocommerce_after_shipping_rate` — action `(WC_Shipping_Rate $rate, int $index)`                                          | Viser valg af afhentningssted ved den valgte fragtpris i klassisk checkout.                                                                                          |
    | `woocommerce_after_checkout_validation` — action `(array $data, WP_Error $errors)`                                         | Validerer afhentningssted i klassisk checkout og tilføjer fejl.                                                                                                      |
    | `woocommerce_checkout_create_order` — action `(WC_Order $order, array $data)`                                              | Tilføjer det verificerede afhentningssted fra klassisk checkout før ordren gemmes.                                                                                   |
    | `woocommerce_store_api_checkout_update_order_from_request` — action `(WC_Order $order, WP_REST_Request $request)`          | Validerer/gemmer checkoutblokkens valg via Store API.                                                                                                                |
    | `woocommerce_order_details_after_order_table` — action `(WC_Order $order)`                                                 | Viser det gemte afhentningssted på ordredetaljer.                                                                                                                    |
    | `woocommerce_email_after_order_table` — action `(WC_Order $order, bool $sent_to_admin, bool $plain_text, WC_Email $email)` | Viser afhentningsstedet i HTML-/tekstmail; Smart Sends callback bruger de første tre argumenter.                                                                     |
    | `woocommerce_product_options_shipping` — action `()`                                                                       | Tilføjer toldfelter på produktets fane Forsendelse.                                                                                                                  |
    | `woocommerce_admin_process_product_object` — action `(WC_Product $product)`                                                | Sætter indsendte toldfelter på produktobjektet, før WooCommerce gemmer det.                                                                                          |

    Smart Send bruger også WooCommerces registrering af Blocks-integrationer og HPOS-kompatibilitet. Disse registreringer og det eksperimentelle Blocks-filter for data-attributter er implementeringsdetaljer; brug filtrene for afhentningssteder ovenfor til fælles adfærd på tværs af checkouttyper.
  </Accordion>

  <Accordion title="Valgfrit WooCommerce Subscriptions" id="optional-woocommerce-subscriptions">
    Smart Send bruger disse Subscriptions-filtre med prioritet 10:

    | Filter                                | Argumenter og returværdi                                                             | Smart Sends adfærd                                                                                                 |
    | ------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
    | `wc_subscriptions_renewal_order_data` | `(array $metadata) → array`                                                          | Udelader afsluttede bookingresultater og kopierede trackingoplysninger.                                            |
    | `wcs_renewal_order_items`             | `(WC_Order_Item[] $items, WC_Order $renewal, WC_Subscription $subscription) → array` | Viderefører præcise kildeidentiteter under kopiering af ordrelinjer.                                               |
    | `wcs_renewal_order_created`           | `(WC_Order $renewal, WC_Subscription $subscription) → WC_Order`                      | Kobler fordelinger til nye ordrelinje-ID'er og fjerner midlertidige markører; tvetydige planer kræver nulstilling. |

    Bevar filtrenes returværdier, når du tilføjer egne Subscriptions-callbacks. Integrationen følger Subscriptions 4.9+'s API til datakopiering; test af hookkontrakten er ikke test af det kommercielle plugins planlagte fornyelser/betalingsmotor. Se [kompatibilitet](/da/integrations/woocommerce/introduction#compatibility).
  </Accordion>

  <Accordion title="Hvad er verificeret?" id="verification-scope">
    Eksemplerne er kørt mod pluginets rigtige PHP-værdiobjekter med isolerede WordPress-/WooCommerce-testdobler. Kontrollerne dækker almindelig tekst i labels, sortering/antal af afhentningssteder, automatisk kontra eksplicit vægt, kollifordeling og resultater for udgående/retur-events. De beviser ikke transportørens accept, samspillet med dine øvrige plugins eller levering til et eksternt system. Kontrollér det berørte forløb i din konfigurerede testshop før deployment.
  </Accordion>
</AccordionGroup>

<span id="metadata" />

## Metafelter

Smart Send gemmer forskellige oplysninger på ordren, dens fragtlinjer og katalogprodukterne. Nøglerne nedenfor beskriver disse data og kan ikke bruges på tværs af objekterne. Brug helst de dokumenterede hooks og [API'et](#api), når du ændrer bookingadfærd. Læs metadata gennem WooCommerces CRUD-objekter, så integrationen fungerer med både HPOS og traditionel ordreopbevaring.

Følg [WooCommerces HPOS-vejledning](https://developer.woocommerce.com/docs/features/orders/high-performance-order-storage/recipe-book/) <Icon icon="arrow-up-right" size={12} /> ved læsning og tilsigtede opdateringer: Hent en `WC_Order`, brug objektets metadatametoder, og gem gennem objektet. Antag ikke, at ordrer er WordPress-indlæg.

### Konfiguration på fragtlinjen

Værdierne tilhører den enkelte `WC_Order_Item_Shipping`, ikke `WC_Order`. WooCommerce kopierer dem fra den valgte Smart Send-fragtpris, når fragtlinjen oprettes.

| Nøgle                                   | Gemt værdi                            | Betydning                                                                                                       |
| --------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `smart_send_shipping_method`            | Streng, eksempelvis `postnord_agent`. | Den udgående Smart Send-ydelse, der er valgt til fragtmetoden.                                                  |
| `smart_send_return_method`              | Ydelseskode som streng eller tom.     | Den opsatte returydelse. En Smart Send-fragtlinje uden denne værdi har ingen opsat returydelse.                 |
| `smart_send_auto_generate_return_label` | `'yes'` eller `'no'`.                 | Det gemte valg om at inkludere retur ved booking af udgående fragt. Det booker ikke noget, når ordren oprettes. |

Værdierne er en kopi af metodens konfiguration på det tidspunkt, hvor fragtlinjen oprettes. Ændringer af zonens standarder omskriver ikke eksisterende fragtlinjer. En ydelse valgt til én booking i ordrepanelet overskriver heller ikke værdierne. Læs dem med `$shipping_item->get_meta( $key, true )`. Brug `SS_SHIPPING_WC()->method_resolver()`, når du skal bruge den fundne bookingydelse, inklusive den særskilte kobling for WooCommerces egen Gratis fragt.

### Leveringskonfiguration og bookingresultater på ordren

Læs felterne fra en `WC_Order`, som du henter med `wc_get_order()`. Leveringskonfiguration håndteres af `Smart_Send\Delivery\Order_Meta`, mens bookingresultater håndteres af `Smart_Send\Fulfillment\Shipment_IDs`.

| Nøgle                          | Gemt værdi                              | Betydning                                                                                                                                                                                            |
| ------------------------------ | --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ss_shipping_order_agent_no`   | Afhentningsstedets nummer som streng.   | Det valgte steds nummer hos transportøren. Det skal passe til det gemte objekt for stedet.                                                                                                           |
| `_ss_shipping_order_agent`     | Almindeligt objekt med afhentningsdata. | Den gemte adresse og øvrige oplysninger om afhentningsstedet. Begge checkout-typer gemmer et sted, som er verificeret på serveren.                                                                   |
| `ss_shipping_order_parcels`    | Array med listen `specs`.               | Genanvendelig fordeling af **ordrelinje-id'er** og antal på kolli. Eksplicitte vægte og mål gemmes som `null`.                                                                                       |
| `_ss_shipping_label_id`        | Smart Send-forsendelses-id som streng.  | Den senest registrerede vellykkede **udgående** forsendelse.                                                                                                                                         |
| `_ss_shipping_return_label_id` | Smart Send-forsendelses-id som streng.  | Den senest registrerede vellykkede **returforsendelse**.                                                                                                                                             |
| `_ss_shipping_labels`          | Liste af bookingposter.                 | De seneste 50 registrerede forsendelser med den ældste først inden for listen. Hver post har `direction` (`outbound` eller `return`), `shipment_id` (streng) og `booked_at` (ISO 8601-streng i UTC). |

Forsendelses-id'erne identificerer Smart Send-forsendelser. De er ikke trackingnumre, PDF-adresser eller WordPress-vedhæftnings-id'er. Historikken har én post pr. forsendelse, ikke pr. kolli, og indeholder ikke løbende transportørhændelser. Udgående fragt og retur registreres hver for sig, også når udgående booking lykkes, men retur fejler. Brug `SS_SHIPPING_WC()->shipment_ids()->get( $order, false )` til det seneste udgående id, `true` til retur eller `labels( $order )` til historikken. Id-læseren returnerer en tom streng, når der ikke er gemt et id.

Se [leveringsdata og lagring](#delivery-details-and-persistence) for forskellen på indsendte værdier, filterændringer og gemte data.

<AccordionGroup>
  <Accordion title="Objektet for et afhentningssted" id="metadata-pickup-point">
    Kendte egenskaber omfatter `agent_no`, `company`, `address_line1`, `address_line2`, `postal_code`, `city` og `country`. Et sted kan også indeholde `id`, `carrier`, `name_line1`, `name_line2`, `distance`, `coordinates` og `opening_hours`. Antag ikke, at alle valgfrie egenskaber findes. Landet er en ISO 3166-1 alpha-2-kode. Koordinater har `latitude` og `longitude`, og åbningstidsrækker har `day`, `opens` og `closes`.

    Brug `SS_SHIPPING_WC()->order_meta()->read( $order )->get_pickup_point()` for at få en `Smart_Send\Delivery\Pickup_Point` eller `null`. Det typede objekt har getters og `to_array()`, så kalderen ikke behøver at afhænge af alle rå egenskaber. Brug `smart_send_delivery_details` til bookingændringer. At ændre det rå afhentningsnummer alene erstatter ikke opslag og validering af et sted, der passer til ydelsen.
  </Accordion>

  <Accordion title="Gemt kollifordeling" id="metadata-parcel-plan">
    Eksemplet viser to enheder fra ordrelinje `123` i ét kolli. Id'et er lokalt for ordren; det er hverken et produkt-id eller variations-id.

    ```json theme={null}
    {
      "specs": [
        {
          "reference": "1",
          "weight": null,
          "length": null,
          "width": null,
          "height": null,
          "items": [
            { "order_item_id": 123, "quantity": 2, "name": "Cotton T-shirt" }
          ]
        }
      ]
    }
    ```

    `reference` og varens valgfrie `name` er tekster til visning, ikke identiteter for ordrelinjer. Antal og ordrelinje-id'er er positive heltal. `Parcel_Plan::from_array()` læser det kanoniske format; fordelingen skal også kontrolleres mod den aktuelle ordres linje-id'er og antal. Ved lagring gennem `Order_Meta` erstattes de fire vægt- og målfelter med `null`. En tom `specs`-liste betyder ét kolli med alle varerne.

    Kopiér ikke arrayet uændret til en anden ordre. Ændres linjer eller antal, skal en gemt fordeling, der ikke længere passer, nulstilles før booking. Se [leveringsdata og lagring](#delivery-details-and-persistence) for fordelingsregler og de mål, der kun gælder én booking.
  </Accordion>

  <Accordion title="Fornyelser og felter, som tilhører andre integrationer" id="metadata-renewals">
    Subscriptions-integrationen udelader `_ss_shipping_label_id`, `_ss_shipping_return_label_id` og `_ss_shipping_labels` fra fornyelsens metadata. Den bevarer genanvendelig leveringskonfiguration og knytter kollifordelingen til fornyelsens nye ordrelinje-id'er. Kan sammenhængen ikke verificeres, kan `ss_shipping_order_parcels` indeholde den interne indpakning `unmapped_subscription_plan`, som kræver en udtrykkelig nulstilling. Den markerer en fejl og er ikke et understøttet format, du skal skrive som kollifordeling.

    `_smart_send_renewal_source_item` er en midlertidig intern markering på produktordrelinjer med `order_id` og `item_id`. Integrationen fjerner den efter behandlingen af de kopierede linjer. Brug den ikke som et permanent integrationsfelt.

    `_wc_shipment_tracking_items` tilhører WooCommerce Shipment Tracking. Smart Send bruger udvidelsens API til tracking og udelader kopierede trackingposter fra fornyelser; Smart Send definerer ikke udvidelsens metadataformat. `_vc_aio_options` tilhører vConnect og læses af hensyn til kompatibilitet ved opslag af leveringsdata. Ingen af de to felter er en skrivekontrakt, som Smart Send ejer.
  </Accordion>

  <Accordion title="Forsendelsesvalg og lagring" id="delivery-details-and-persistence">
    En værdi indsendt fra ordresiden har forrang frem for den gemte værdi, før `smart_send_delivery_details` kører. Efter vellykket booking gemmes det indsendte valg af afhentningssted og fordelingen af varer på kolli. Den indsendte metode samt kollivægt og mål gælder kun den aktuelle booking. En fejlet booking gemmer ikke ændringerne. Filterets returnerede objekt bestemmer, hvad der bookes, men bestemmer ikke i sig selv, hvad der gemmes.

    Ved en samlet udgående-/returbooking bruges den indsendte kolliplan i begge retninger, medmindre en særskilt returplan tilsidesætter den. En null eller tom plan betyder ét kolli med alle ordrevarer. Én spec uden fordelinger inkluderer også alle varer og kan angive eksplicitte mål. Flere specs kræver fuldstændig fordeling: hver ordreenhed præcis én gang, positive hele antal og ingen dublet af samme ordrelinje inden for én spec. Ukendte ordrelinje-ID'er samt for få eller for mange fordelte enheder afvises.
  </Accordion>
</AccordionGroup>

### Produkternes toldoplysninger

Felterne tilhører en `WC_Product` eller `WC_Product_Variation`, ikke en ordre eller fragtlinje.

| Nøgle                   | Gemt værdi                              | Betydning                                                                                 |
| ----------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------- |
| `_ss_country_of_origin` | Landekode som streng, eksempelvis `DK`. | ISO 3166-1 alpha-2-landekode for det land, hvor varen er fremstillet.                     |
| `_ss_customs_desc`      | Tekststreng.                            | Varebeskrivelse til told.                                                                 |
| `_ss_hs_code`           | Tekststreng.                            | HS-/toldklassifikation. Bevar værdien som tekst frem for at konvertere den til et heltal. |

Brug `wc_get_product()` og produktets `get_meta()` til læsning. Gem en tilsigtet ændring af produktdata med `update_meta_data()` efterfulgt af produktets `save()`. At gemme en værdi afgør ikke, om toldklassifikationen er korrekt.

Booking læser katalogets aktuelle værdier. En variations værdi bruges først, medmindre den er `''` eller `null`; så bruges hovedproduktets værdi. Pluginets produkteditor viser felterne på hovedproduktets Forsendelse-fane og tilføjer ikke en separat editor for hver variation. Felterne kopieres ikke til ordrelinjerne som historiske værdier. Et slettet katalogprodukt kan ikke levere sine tolddata. Se [vejledningen til toldfelter](/da/integrations/woocommerce/shipping-labels#customs-information).

## API

Brug pluginets API i WordPress til at læse Smart Send-data for en eksisterende `WC_Order`. Smart Send og en understøttet WooCommerce-version skal være aktive. Kald eksemplerne, efter Smart Send er initialiseret på `init` med prioritet `0`, for eksempel fra en `init`-callback med prioritet `10` eller et senere ordrehook. Hvis du starter med et ordre-ID, skal du hente ordren med `wc_get_order($order_id)` og kontrollere, at resultatet er en `WC_Order`.

Eksemplerne bruger WooCommerces API'er til ordrer og ordrelinjer og virker derfor med HPOS. De booker ingen forsendelser og kontakter ikke Smart Send API'et. Eksempelfunktionerne bruger præfikset `my_shop_`; vælg dit eget præfiks i din integration.

<AccordionGroup>
  <Accordion title="Hent ordrens afhentningssted" id="get-order-pickup-point">
    <Tabs>
      <Tab title="Beskrivelse">
        `SS_SHIPPING_WC()->order_meta()->read($order)` returnerer `Smart_Send\Delivery\Delivery_Details` med det gemte afhentningssted og den gemte kolliplan. `get_pickup_point()` returnerer et `Smart_Send\Delivery\Pickup_Point` eller `null`. Se [afhentningsstedets metoder](#pickup-point-accessors) for de tilgængelige felter.

        Hjælperen læser det gemte sted; den søger ikke efter nærliggende steder og opdaterer ikke adressen. Hvis der ikke er gemt et Smart Send-afhentningssted, kan den også læse de understøttede afhentningsmetadata fra vConnect. Et agentnummer, der er gemt alene, giver ikke et komplet afhentningsstedsobjekt. De enkelte felter kan være `null`.

        `get_parcel_plan()` på samme details-objekt returnerer den gemte plan eller `null`. Brug `SS_SHIPPING_WC()->order_meta()->parcel_plan_error($order)` til at skelne mellem en manglende plan og en ugyldig gemt kollifordeling; metoden returnerer en forklaring eller `null`. Disse gemte oplysninger fastlægger ikke fragtmetoden; brug det næste eksempel til det.
      </Tab>

      <Tab title="Eksempel">
        Returnér det gemte steds identitet og adresse eller `null`, hvis der ikke er et sted. Escape de enkelte værdier til den relevante outputkontekst, hvis du viser dem i HTML.

        ```php theme={null}
        function my_shop_get_order_pickup_point( \WC_Order $order ): ?array {
        	$point = SS_SHIPPING_WC()->order_meta()->read( $order )->get_pickup_point();

        	if ( null === $point ) {
        		return null;
        	}

        	return array(
        		'agent_no'      => $point->get_agent_no(),
        		'carrier'       => $point->get_carrier(),
        		'company'       => $point->get_company(),
        		'address_line1' => $point->get_address_line1(),
        		'address_line2' => $point->get_address_line2(),
        		'postal_code'   => $point->get_postal_code(),
        		'city'          => $point->get_city(),
        		'country'       => $point->get_country(),
        	);
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Hent fragtmetoder og standardvalg til booking" id="get-order-shipping-methods">
    <Tabs>
      <Tab title="Beskrivelse">
        Du arbejder med to forskellige slags ID'er:

        * `$order->get_shipping_methods()` returnerer de WooCommerce-fragtlinjer, der er gemt på ordren. `get_method_id()` identificerer WooCommerce-metoden, for eksempel `smart_send_shipping` eller `free_shipping`; `get_instance_id()` identificerer fragtmetodens instans i fragtzonen.
        * `SS_SHIPPING_WC()->method_resolver()` finder ét Smart Send-service-ID for hver retning, for eksempel `postnord_agent` eller `postnord_returndropoff`. Den læser metadata på ordrens Smart Send-fragtlinje, den aktuelle [tilknytning til WooCommerces gratis fragt](/da/integrations/woocommerce/shipping-methods#native-free-shipping) eller understøttede tredjepartsmetoder.

        `resolve_outbound($order)` og `resolve_return($order)` returnerer `''`, hvis der ikke kan findes en service. Hvis en Smart Send-fragtlinje ikke har en returmetode, kaster `resolve_return()` en `Smart_Send\Booking\Exceptions\Booking_Exception`; eksemplet bevarer denne forskel i `return_error`. `is_auto_return_enabled($order)` læser indstillingen for automatisk returlabel, som er gemt på fragtlinjen.

        Dette er de standardvalg, der udledes for ordren. De omfatter ikke ugemte valg i ordrebilledet, indsendte ændringer for en booking eller ændringer fra `smart_send_delivery_details`. De fortæller heller ikke, hvilken service en tidligere forsendelse faktisk blev booket med; læs det fra det `Booked_Shipment`, som leveres til en [booking-action](#smart-send-booking-completed).
      </Tab>

      <Tab title="Eksempel">
        Returnér både WooCommerce-fragtlinjerne og de udledte Smart Send-standardvalg. Returfejlen er almindelig tekst; escape den, før du viser den i HTML.

        ```php theme={null}
        function my_shop_get_order_shipping_methods( \WC_Order $order ): array {
        	$shipping_lines = array();

        	foreach ( $order->get_shipping_methods() as $item_id => $item ) {
        		$shipping_lines[] = array(
        			'order_item_id' => (int) $item_id,
        			'method_id'     => $item->get_method_id(),
        			'instance_id'   => $item->get_instance_id(),
        			'title'         => $item->get_method_title(),
        		);
        	}

        	$resolver      = SS_SHIPPING_WC()->method_resolver();
        	$return_method = '';
        	$return_error  = null;

        	try {
        		$return_method = $resolver->resolve_return( $order );
        	} catch ( \Smart_Send\Booking\Exceptions\Booking_Exception $exception ) {
        		$return_error = $exception->getMessage();
        	}

        	return array(
        		'shipping_lines' => $shipping_lines,
        		'outbound'       => $resolver->resolve_outbound( $order ),
        		'return'         => $return_method,
        		'return_error'   => $return_error,
        		'auto_return'    => $resolver->is_auto_return_enabled( $order ),
        	);
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Hent gemte bookinger" id="get-order-bookings">
    <Tabs>
      <Tab title="Beskrivelse">
        `SS_SHIPPING_WC()->shipment_ids()` læser de forsendelsesreferencer, der er gemt på ordren:

        | Metode               | Resultat                                                                                                                                    |
        | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
        | `get($order, false)` | Seneste gemte forsendelses-ID for udgående fragt eller `''`.                                                                                |
        | `get($order, true)`  | Seneste gemte forsendelses-ID for returfragt eller `''`.                                                                                    |
        | `labels($order)`     | Gemte historikposter, ældste først; hver post indeholder `direction`, `shipment_id` og `booked_at`. Manglende historik giver et tomt array. |

        `direction` er `outbound` eller `return`; `booked_at` er et ISO 8601-tidsstempel i UTC eller `null`, hvis det ikke findes. Plugin'et gemmer de seneste 50 historikposter samlet for begge retninger. Det seneste ID for hver retning gemmes særskilt, så et ID kan findes, selv om `labels()` er tomt. En post svarer til én forsendelse, som kan indeholde flere kolli.

        Dette er gemte bookingreferencer. De indeholder ikke aktuel transportørstatus, trackinglinks, dokumenter eller det komplette `Booked_Shipment`. Lyt til [smart\_send\_booking\_completed](#smart-send-booking-completed) eller [smart\_send\_order\_fulfilled](#smart-send-order-fulfilled), og brug [metoderne til bookingresultater](#read-booked-results), hvis du skal læse dokumenter og trackingoplysninger fra bookingresultatet. Et `Fulfillment_Result` beskriver det enkelte forløb, som kan have vellykket udgående fragt og fejlet returfragt; det gendannes ikke fra ordrehistorikken.
      </Tab>

      <Tab title="Eksempel">
        Læs det seneste forsendelses-ID for hver retning og den gemte historik hver for sig. Antag ikke, at en vellykket udgående booking også har oprettet en returforsendelse.

        ```php theme={null}
        function my_shop_get_order_bookings( \WC_Order $order ): array {
        	$shipments = SS_SHIPPING_WC()->shipment_ids();

        	return array(
        		'latest_outbound_id' => $shipments->get( $order, false ),
        		'latest_return_id'   => $shipments->get( $order, true ),
        		'history'           => $shipments->labels( $order ),
        	);
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Læs afhentningsstedets oplysninger" id="pickup-point-accessors">
    `Pickup_Point` har `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()` og `get_opening_hours()`. Valgfrie værdier kan være null. Åbningstider er en liste af rækker med `day`, `opens`, `closes`: dagen er et engelsk ugedagsnavn med små bogstaver, og tider bruger `HH:MM:SS`. En tom liste betyder ukendte åbningstider. `to_array()` giver en serialiserbar repræsentation; det er ikke en tilladelse til at stole på navne eller adresser indsendt fra klienten.
  </Accordion>

  <Accordion title="Læs bookingresultatet" id="read-booked-results">
    `Booked_Shipment` har `get_shipment_id()`, `get_carrier()`, `get_service_code()`, `is_return()`, `get_state()`, `get_booked_at()`, `get_tracking_code()`, `get_tracking_url()`, `parcels()`, `documents()` og `codes()`. Valgfrie trackingfelter kan være null. `label_document()` returnerer et `Shipment_Document` eller null; antag ikke, at alle resultater indeholder en PDF. Dokumentets `download_url()` vælger den lokale kopi, når den findes, ellers Smart Send-URL'en.

    `Fulfillment_Result::get_steps($shipment)` angiver `save_documents` (`true`, `false` eller `'failed'`), `order_note` (boolean), `tracking` (om videresendelse var ønsket) og `order_status` (status eller `false`). Trackingtrinnet beviser ikke, at en valgfri tredjepartsintegration var installeret eller sendte en e-mail.

    Brug `get_order_note_id($shipment)` til den gemte notes heltals-ID eller null. `get_order_note($shipment)` giver note-HTML til PHP-kode. Den serialiserbare `to_array()` indeholder i stedet et `order_note`-objekt med `id`, ikke note-HTML. Rækkerne har `direction`, `status` (`fulfilled`/`failed`) og shipment/steps/warnings eller en fejl. `get_error_details($is_return)` returnerer null eller et array med `message`, `response_id`, `fields` og `html`; behandl `message` som almindelig tekst, og escape output korrekt.
  </Accordion>
</AccordionGroup>
