Shipping assistant API integration
A guide to implement the Shipping API
Important terms
- Checkout API: API implemented by Klarna. The Merchant calls this API to start an order session or manage it.
- Shipping API: API specified by Klarna; must be implemented by the Integrator (TMS) (see below). The Klarna Shipping Assistant queries this API to retrieve shipping options dynamically.
- Integrator: Implementer of the Shipping API. Usually, this is a logistics partner, like Unifaun or Consignor. In a direct integration, the Merchant can take this role.
What is the ideal integration?
An ideal integration with the Shipping API enables the following:
- Shipping options are shown within the Klarna Checkout, based on real-time user data.
- The user’s selected option is saved, and a preliminary shipment is created based on it. The preliminary shipment can be later used by the merchant to print the actual shipping label.
- Tracking is shared with Klarna after the purchase is completed.
Please note that to use the Klarna Shipping Assistant, you may have to adjust your Checkout integration. More info about that is in this section.
Authorization
This section describes how to authorize requests from the Klarna Shipping Assistant.
Use case
The user has entered the checkout, and Klarna tries to obtain authentication from the Integrator.
Prerequisite
The merchant has provided Klarna with authentication credentials. More information can be found in the Getting Started section.
Description
Communications between the Klarna Shipping Assistant and the Integrator must be authenticated using a bearer token scheme. Consequently, each request has a header like this:
Authorization: Bearer <token>
Where <token>
is a secret string provided by the Integrator. To obtain it, Klarna Shipping Assistant calls POST /auth
with credentials provided by the Merchant. This is a payload example:
{
"identifier": < username > "secret": {
"nonce": < random string > "digest": < encoded nonce + key >
}
}
The digest is calculated by concatenating the (random) nonce
and the (Merchant-provided) key and then feeding the result into the SHA-256 algorithm. To check that the secret is correct, the Integrator must compare our value by doing the same process on their end:
digest = sha256(nonce + key)
We recommend the Integrator give a unique token per merchant and let the token expire after a reasonable time (1h is a good duration). If the Klarna Shipping Assistant provides an old or wrong token to a call other than POST /auth
, the Integrator must answer with HTTP 401 (Unauthorized). If the Klarna Shipping Assistant provides the wrong credentials to POST /auth
, the Integrator must also answer with HTTP 401 (Unauthorized).
The Klarna Shipping Assistant will cache the bearer token until an HTTP 401 response is received and then fetch a new one.
Preview
This section describes what preview options are and how to set them.
Use case
The user has entered the checkout.
Prerequisite
No address data is available for the user.
Description
When a new user enters the checkout, Klarna has no data to pre-fill the address. To ensure a user-friendly experience, we show placeholder options based only on the country of purchase. These temporary options are called preview options.
This is what it looks like:
To make this work, the Integrator needs to be able to return shipping options for partial address data on a POST /shippingoptions
call (described in the next section). A partial address could be only the country in cases like the above. The Integrator must mark these options with a preview
flag.flag.
Once Klarna has a full address, the Klarna Shipping Assistant will call the endpoint again with the complete information. Then the Integrator must answer with fully valid (non-preview) shipping options.
Shipping options
This section describes how to provide shipping options to the Klarna Shipping Assistant.
Use case
The user is in the checkout and has provided address data, or their address data is prefilled.
Prerequisite
Complete address data is available for the user, and the authentication call to the Shipping API was successful.
Description
The Klarna Shipping Assistant obtains shipping options from the Integrator by calling POST /shippingoptions
every time the user updates their cart or address information. This call must be authenticated using the bearer token obtained previously, as described in the Authorization section.
You can test a Shipping API implementation and see how the shipping selector looks in our test tool, Shipwreck. This is an example request from Shipwreck:
path: /shippingoptions
method: POST
Headers: Content-Type: application/vdn.klarna.shipping.get_options-v1+json
body: {
"session_id": "f7b7dda8-c9a6-405d-8cca-1c3cbdfda1c0",
"locale": "sv-SE",
"currency": "SEK",
"geoblocking": false,
"recipient": {
"given_name": "Klara",
"family_name": "Joyce",
"street_address": "Sveavägen 42",
"postal_code": "111 34",
"city": "Stockholm",
"country": "SE",
"phone": "+46708800000",
"email": "partner@klarna.com",
"customer_type": "person"
},
"order": {
"id": "17d4cd21-99cd-4ffa-97d6-257b258cf053",
"total_amount": 1130,
"total_tax": 25,
"tags": ["member"],
"lines": [{
"type": "physical",
"reference": "sku-1234",
"quantity": 1,
"unit_price": 100,
"tax_rate": 2500,
"total_tax_amount": 25,
"total_price_including_tax": 125,
"total_discount_amount": 0,
"attributes": {
"weight": 890,
"tags": ["out_of_stock"]
}
}, {
"type": "physical",
"reference": "sku-4321",
"quantity": 8,
"unit_price": 0,
"tax_rate": 0,
"total_price_including_tax": 1005,
"total_discount_amount": 0
}],
"total_amount_without_shipping_fee": 1130,
"total_tax_without_shipping_fee": 25
}
}
Klarna passes the order information to the Shipping API. The order information is set by the Merchant while creating a Checkout session.
To enhance the shipping experience, we added shipping attributes to the order and order line level. Like the rest of the order information, these attributes will be passed on to the shipping API. The attributes can be used to set the rules about which shipping options should be shown.
- Weight and dimensions.
- Tags.
The following is a response example from an Integrator (adapted from our test integration tool, Ghostship):
{
"shipping_options": [{
"id": "id-1070",
"type": "postal",
"carrier": "postnord",
"name": "Postal delivery",
"price": 0,
"tax_rate": 0,
"delivery_time": {
"interval": {
"earliest": 4,
"latest": 6
}
},
"class": "standard"
}, {
"id": "id-1000",
"type": "pickup-box",
"carrier": "instabox",
"name": "Pickup Box",
"price": 100,
"tax_rate": 0,
"delivery_time": {
"latest": "2019-10-15T19:00:00Z"
},
"locations": [{
"id": "loc-2",
"name": "Coop Loet",
"price": 500,
"address": {
"street_address": "Storgatan 59",
"postal_code": "97232",
"city": "Luleå",
"country": "SE"
},
"coordinates": {
"lat": 65.5850107,
"lng": 22.1558937
},
"operational_hours": {
"default": [{
"always_open": true
}]
}
}, {
"id": "loc-4",
"name": "BURMANS BUTIK I BERGVIKEN",
"price": 0,
"address": {
"street_address": "BLOMGATAN 17",
"postal_code": "97331",
"city": "Luleå",
"country": "SE"
},
"coordinates": {
"lat": 65.5992109,
"lng": 22.1487749
},
"operational_hours": {
"overrides": {
"weekday": {
"mon": [{
"always_open": true
}],
"tue": [{
"open": "09:00",
"close": "18:00"
}],
"thu": [{
"open": "09:00",
"close": "19:00"
}]
}
},
"default": [{
"open": "08:00",
"close": "18:30"
}]
}
}],
"class": "economy"
}, {
"id": "id-1050",
"type": "delivery-address",
"carrier": "budbee",
"name": "To door delivery",
"price": 2500,
"tax_rate": 2500,
"delivery_time": {
"earliest": "2019-10-16T16:00:00Z",
"latest": "2019-10-16T20:00:00Z"
},
"addons": [{
"category": "notifications",
"type": "sms"
}, {
"category": "delivery",
"type": "additional-instructions",
"max_length": 100
}],
"class": "standard"
}]
}
You can find the complete list of supported shipping types
, services
and carriers
in our API documentation. Below you can find a non-exhaustive summary of the key information.
Shipping types
Each shipping option must have a shipping type
indicating whether, for example, it is a home delivery option. These are some of the supported types:
delivery-address
- Delivery to door / address. The final selected option will contain an address and can contain a timeslot.pickup-box
- Delivery to a pickup locker/box. The final selected option will contain a location.pickup-point
- Delivery to a pickup point. The final selected option will contain a location.pickup-merchant-store
- Delivery to a merchant store for pickup. The final selected option will contain a location.postal
- Delivery of a package/letter using the postal network.generic-pickup
- Delivery to a pickup point when location is unknown.generic-shipping
- Shipping option when the carrier decides on the shipping method.office-delivery
- Delivery to an office address. For example, to an office reception.boat-delivery
- Delivery by boat.digital
- Delivery via email or SMS.click-collect
- Order goods online for reservation and pick them up at a merchant store.pickup-warehouse
- Delivery to a merchant warehouse for pick up.
The type
attribute controls which name KSA will show in the shipping option. For example, delivery-address
is shown in English as “To door delivery”.
The banner about digital delivery will be shown if there is a digital item in the order. When the order has a digital item but no physical items, Klarna Shipping Assistant will not request any shipping options from TMS, the shipping selector will not be shown, and the shipping type
will be set to digital
.
Add-ons
Add-ons are additional services or information that can be added to an option. They can be marked as mandatory. Here are some examples:
addon_notification
- Booking email or SMS notification. The final selected option will contain an email address and/or a phone number.addon_delivery
- Adding entry code (door code) and delivery instructions. The final selected option will contain the door code and instruction text.
Delivery time
A shipping option’s delivery time is crucial information for the users. It can be provided in two different formats:
- You can use an offset in days from the current date to show intervals. For example,
"delivery_time": {
"interval": {
"earliest": 1,
"latest": 3
}
}
This will be shown as 1-3 working days.
- To show an exact time, you can use an ISO 8601 date-time (you can try it out in this tool). For example,
"delivery_time": {
"latest":"2019-08-28T12Z"
}
Assuming today is 2019-08-27 in Sweden (UTC+2 in the summer), this will be shown as “Tomorrow at 14h”(Z is the same as +00:00. It indicates UTC+0, Greenwich time).
Location search
This section describes the pickup point map and the associated location search.
Use case
The user opens the pickup point map and searches for locations.
Prerequisite
The user inserted a new postal code into the location search field.
Description
Pickup locations are presented on a map view. The user can search for new locations by postal code.

Whenever the user inserts a new postal code, Klarna will call POST /shippingoptions
with country
and poand postal_code
. The following swimlane explains the flow:

Be careful when implementing your /shippingoptions
endpoint. From the Integrator’s perspective, a location search looks like a preview options call, since it uses this endpoint with an incomplete address. However, Klarna Shipping Service discards any changes other than the locations.
Select shipping option
This section describes how Klarna finalizes the selected shipping option.
Use case
The user is completing the purchase (pushing the buy button).
Prerequisites
A valid (non-preview) shipping option is selected. The user has not tried to finalize before.
Pitfalls
Receiving this call does not guarantee the purchase is final. If something fails, this can lead to a PUT
operation (see Update Shipping Option section).
Description
The first time the user tries to finalize their purchase by pressing the buy button, the Klarna Shipping Assistant validates the selected shipping option with POST /shipment
. Finalizing can fail for several reasons (for example, the payment method is rejected), so this is not a guarantee that the shipment is final. Depending on the details mentioned in the next section, subsequent attempts to finalize might be realized as PUT /shipment/<shipment ID>
.
If the Integrator receives valid data, they must respond with HTTP 201 (Created) and a valid payload:
{
"selected_shipping_option": {...},
"shipment_id": <shipment ID>,
"shipments": [...]
}
Where <shipment ID>
is a unique identifier for the (pre-reserved) shipment. The response must also set the Location
header:
Location: <Integrator's base URL>/shipment/<shipment ID>
The shipment ID must be unique per session_id
(this is sent in the request payload). Its presence, and the presence of the location header, will be taken as confirmation that an entry has been correctly created in the Integrator’s service. This information will be forwarded to the merchant once the purchase is confirmed, and they can print the shipping label.
The following image shows the ideal workflow:

Klarna uses different identifiers during the API flow. To avoid confusion, please check this swimlane.
The following is an example request from our test tool Shipwreck:
{
"session_id": "9e8de95f-f8b7-4711-85d9-53ac848ee0d8",
"locale": "sv-SE",
"currency": "SEK",
"recipient": {
"given_name": "Klara",
"family_name": "Joyce",
"street_address": "Sveavägen 42",
"postal_code": "111 34",
"city": "Stockholm",
"country": "SE",
"phone": "+46708800000",
"email": "partner.kss@klarna.com",
"customer_type": "person"
},
"order": {
"id": "6ad9a637-866c-484f-823e-1c86a67e7be2",
"total_amount": 1130,
"total_tax": 25,
"lines": [{
"type": "physical",
"reference": "sku-1234",
"quantity": 1,
"unit_price": 100,
"tax_rate": 2500,
"total_tax_amount": 25,
"total_price_including_tax": 125,
"total_discount_amount": 0
}, {
"type": "physical",
"reference": "sku-4321",
"quantity": 8,
"unit_price": 0,
"tax_rate": 0,
"total_price_including_tax": 1005,
"total_discount_amount": 0
}],
"total_amount_without_shipping_fee": 1130,
"total_tax_without_shipping_fee": 25
},
"selected_shipping_option": {
"id": "id-1050",
"name": "Budbee 2 home",
"type": "delivery-address",
"class": "express",
"carrier": "budbee",
"price": 5000,
"tax_rate": 2500,
"addons": [{
"category": "notifications",
"type": "sms",
"required": false,
"data": {
"text": "+46708800000",
"selected": false
},
"default": false
}, {
"category": "notifications",
"type": "email",
"required": false,
"data": {
"text": "partner.kss@klarna.com",
"selected": false
},
"default": false
}, {
"category": "delivery",
"type": "phone-required",
"required": false,
"data": {
"selected": false
},
"default": false
}, {
"category": "delivery",
"type": "entry-code",
"required": false,
"data": {
"selected": false
},
"default": false
}, {
"category": "delivery",
"type": "additional-instructions",
"max_length": 100,
"required": false,
"data": {
"selected": false
},
"default": false
}],
"valid": true
}
}
Example request from our test tool Shipwreck
{
"header": "Location: https://foo.bar/c2059e35-58b1-4482-ad55-5e7ef541eae4",
"body": {
"shipment_id": "100",
"selected_shipping_option": {
"carrier": "budbee",
"carrier_product": {
"name": "MyPack",
"identifier": "10",
"addon_identifiers": ["1", "2"]
}
},
"shipments": [{
"carrier": "Global carrier company",
"tracking_id": "12345-6"
}]
}
}
Example response from our test integration tool, Ghostship
Update shipping option
This section describes how and when the Klarna Shipping Assistant updates the finalized shipping option.
Use case
The user tries to finalize after a previous finalize attempt.
Prerequisite
A previous POST /shipment
call was successful (see Save shipping option section).
Description
Klarna validates several items when the user completes their purchase (for example, shipping options and payment method). If any of those fail, the purchase will not proceed.
For example, the POST /shipment
call may be successful, but the payment method may fail. The user then gets an error message and can change their details before trying again. This allows them to change anything, like adding items to the cart or changing the shipping address. When the user completes the checkout for the second time, the Klarna Shipping Assistant will validate the selected shipping option again to ensure the user’s choice is still valid.
If the Klarna Shipping Assistant has an available shipment ID from a previous POST /shipment
call, the subsequent attempts to finalize will be realized as PUT /shipment/<shipment ID>
instead.
The Shipping API will not communicate whether the order is completed successfully. This means that the Klarna Shipping Service can update the shipping option several times, sometimes with long waits until the order is placed. The merchant will know when the order is completed through the Order Management API.
Tracking
This section describes how to provide Klarna with tracking information.
Use case
The user has completed the purchase.
Prerequisite
The order is successfully completed.
Description
Suppose the Integrator does not provide complete tracking information on the POST /shipment/<shipment ID>
or PUT /shipment/<shipment ID>
responses. In that case, the Klarna Shipping Assistant will call GET /shipment/<shipment ID>
periodically after completing the purchase. The expected response format is the same as in the POST
and PUT
operations.
The response to this call should list all shipments connected to this purchase and contain tracking numbers (tracking_id
) for each shipment. Klarna uses the tracking information to allow users to track their parcels and get notified upon any updates.
Alternatively, you can provide us with the tracking number and carrier information via the order management API. Just follow these instructions.