Returns integration
This guide takes you through the basic setup and steps to integrate a return flow with Helthjem.
Steps:
- Authorize
- Check address for coverage
- Fetch available pickup dates
- Book return
- Provide label or return code
- Track return
Choose a transport solution
See our page with descriptions on Delivery Methods to find an appropriate Transport Solution. A return transport solution determines which return products the customer can be offered, and the order Helthjem falls back through if the first one is not available for the address.
| transportSolutionId | Name | Falls back through | Use when |
|---|---|---|---|
| 21 | Helthjem retur | 4 | Home pickup only |
| 33 | Helthjem retur m/retur via butikk | 4 → 56 → 20 | Home pickup, labeled PUDO as backup |
| 63 | Helthjem retur butikk | 56 → 20 | Labeled PUDO only |
| 116 | Etikettløs retur via butikk | 95 | Labelless PUDO only |
| 118 | Helthjem Returpakke | 56 | Labeled Helthjem PUDO only |
| 119 | Pure Helthjem Retur | 4 → 56 | Home pickup, Helthjem PUDO as backup |
| 121 | 100% Etikettløs Retur | 4 → 95 | Labelless throughout |
| 122 | Helthjem retur m/etikettløs PUDO | 4 → 95 → 56 | Labelless first, labeled as last resort |
| 135 | Etikettløs retur via butikk eller PN | 95 → 20 | Labelless PUDO, PostNord as backup |
The freight products these resolve to:
| freightProductId | productName | Return type | Label |
|---|---|---|---|
| 4 | HELTHJEM_RETUR | Home | Label or code |
| 56 | HELTHJEM_SHOP_RETURN | PUDO | Label |
| 95 | HELTHJEM_C2B_PUDO_RETURN | PUDO | Label or code |
| 20 | PN_MYPACK_RETUR | PUDO | Label |
Tip: Use a transport solution with fallbacks (33, 122, 135) in rural or low-coverage areas to raise the share of returns you can accept.
In this guide we will be using transport solution 21 for home pickup and transport solution 116 for labelless drop-off at a service point, in collaboration with the Single Address Check to confirm coverage before booking.
Lets begin
1. Authorize
Use the Authorization endpoint with your client_id and client_secret to obtain a JWT. This token expires in 24hrs, if you store it and refresh it every 12 hours, you will not need to authorize for every request.
Request
{
"client_id": "your-client-id",
"client_secret": "your-secret",
"grant_type": "client_credentials"
}
Response
{
"token": "xxx",
"expires_in": 86400,
"token_type": "Bearer"
}
Authorization: Bearer <token>
Content-Type: application/json
2. Check address for coverage
2.1 Single Address Check
Check coverage of an address with the Single Address Check endpoint for a given address to confirm that we have coverage for a return Transport Solution.
Run the check once per return method you intend to display, so the customer only sees options that are available at their address.
Checkout example
In this example, we want to check that we can collect a return from the doorstep of “Ola Nordman”, who lives at Kongsberggata 18, Oslo 0468. Ola has also sent us his apartment number H0201.
Request
{
"shopId": 1,
"transportSolutionId": 21,
"customerName": "Ola Nordmann",
"address": "Kongsberggata 18 H0201",
"zipCode": "0468",
"postalName": "Oslo",
"countryCode": "NO",
"weight": 1000,
"volume": null
}
Success (200)
{
"productName": "HELTHJEM_RETUR",
"routeName": "21516",
"routing": "1-31/114-43-x21516x385",
"routeAddress": "TÅSENVEIEN 26",
"handoverCity": "OSLO",
"plannedDeparture": "1600"
}
We get the response "productName": "HELTHJEM_RETUR", which confirms that we can collect a return from this address.
Now that the coverage has been confirmed, the Transport solution can confidently be exposed as a return option.
A 400 with "no.carrier.support" means we cannot collect from that address with the chosen transport solution — hide that option in the checkout.
2.2 Nearby Service points
If you wish to offer Service Point drop-off, use the Nearby Service Points endpoint to retrieve the 3 closest locations to an address.
In this example, we will use transportSolutionId: 62, which includes both Helthjem and Postnord service points.
Request
{
"shopId": 1,
"transportSolutionId": 62,
"streetAddress": "Kongsberggata 18",
"zipCode": "0468",
"postalName": "Oslo",
"countryCode": "NO"
}
Response (trimmed)
{
"freightProducts": [
{
"freightName": "Helthjem Hentepakke",
"servicePoints": [
{
"servicePointExternalId": "30694",
"servicePointName": "Joker Toftes Gate",
"openingHours": [
{"day":"MONDAY","from1":"07:00","to1":"00:00"}
],
"visitingAddress": {
"streetName": "TOFTES GATE",
"streetNumber": "12",
"postalCode": "0556",
"postalName": "OSLO",
"countryCode": "NO"
}
}
]
}
]
}
For a return the customer can hand the parcel in at any eligible location, so this is for display only — the service point is not included as a party when booking.
3. Fetch available pickup dates
If the customer chooses Home pickup (TS 21), show available pickup dates. This date is needed in the booking to order a Helthjem driver to pickup the parcel and receive a returnCode.
Skip this step for PUDO returns — there is no date to select.
Note: You need to use "freightProductId": 4, not a transportSolutionId.
Path: /parcels/v1/addresses/find/single/dates
Request
{
"shopId": 16,
"freightProductId": 4,
"zipCode": "0561",
"customerName": "Test customer",
"countryCode": "NO",
"postalName": "Oslo",
"address": "Herslebs gate 2F",
"co": ""
}
Response
{
"dates": [
"2026-06-17",
"2026-06-18",
"2026-06-19",
"2026-06-20",
"2026-06-22",
"2026-06-23",
"2026-06-24",
"2026-06-25",
"2026-06-26",
"2026-06-27",
"2026-06-29",
"2026-06-30"
]
}
Dates we cannot collect on are absent from the list, so present the array as-is.
4. Book the return
Now that we have successfully confirmed that the transport solution is available for an address, book the return using the Booking endpoint.
A return uses the same endpoint and payload shape as an outgoing booking, with the parties swapped. For a C2B return, the customer = consignor and the shop = consignee.
For home pickup, include the date the customer selected as "desiredDeliveryDate".
**Request **(transportSolutionId: 121)
{
"shopId": 1,
"transportSolutionId": 4,
"shipmentId": "",
"desiredDeliveryDate": 20260617,
"parties": [
{
"type": "consignee",
"name": "Demo Shop",
"countryCode": "NO",
"zipCode": "0484",
"address": "Sandakerveien 88",
"phone1": "12345678"
},
{
"type": "consignor",
"name": "Ola Nordmann",
"countryCode": "NO",
"postalName": "Oslo",
"zipCode": "0468",
"address": "Kongsberggata 18",
"phone1": "12345678",
"email": "ola@example.com"
}
],
"items": [
{
"itemNumber": 1,
"weight": 1000,
"width": 12,
"height": 12,
"length": 12,
"contents": "Shoes"
}
]
}
Response
{
"shipmentId": "70724762400784060",
"freightProductId": 4,
"parties":[...]
"items":[
{
"trackingReference": "...",
"returnCode": "H987654"
}
],
"properties":{...},
"orderId": 133370472
}
In this response, you receive the shipmentId and trackingReference as identifiers, and the returnCode where the booking resolved to a labelless product.
For a PUDO return, use a PUDO transport solution (116, 63, 118 or 135) and omit "desiredDeliveryDate".
Tip: Make sure phone1 and email are populated on the consignor. We use them to send the customer the return code and instructions.
5. Provide label or return code
What you give the customer depends on which freight product the booking resolved to. Check "freightProductId" in the response.
Labelled products (4 with label, 56, 20) — fetch a printable label after a successful booking. Use either shipmentId or trackingReference as the identifier. A standard label is 102×192 mm PDF.
Read our label guide for more details and to configure other options.
Request
curl -X GET "https://api.pre.helthjem.no/parcels/v1/labels/{identifier}/unified-large" \
-H "Authorization: Bearer <token>" \
-H "Accept: application/pdf,application/json"
Labelless products (95, and 4 when used without a label) — there is no label. The booking response contains a return code instead:
{
"returnCode": "H987654"
}
Display the return code in your own flow if you want to, and instruct the customer accordingly:
Home pickup: write the code on the parcel and leave it outside by 07:00 on the selected date.
PUDO: write the code on the parcel and drop it at the nearest Helthjem return point
We also send the customer an SMS and an email with the code and instructions, so this step is optional on your side.
6. Track the return
Track return progress via events from booking to arrival.
curl -X GET "https://api.pre.helthjem.no/parcels/v1/tracking/fetch/{identifier}/NO/false" \
-H "Authorization: Bearer <token>" \
-H "Accept: application/pdf,application/json"
Response
[
{
"shipmentNumber": "70724763243779244",
"shopName": "Testbutikken",
"shopId": 1,
"consigneeReference": "shop_ref",
"consignorReference": "cust_ref",
"properties": {},
"items": [
{
"trackingNumber": "370724763243779252",
"returnCode": "H987654",
"freightProductId": 4,
"freightProductName": "HELTHJEM_RETUR",
"parcelStatus": "WAITING_FOR_PACKAGE",
"linkedParcelNumbers": [],
"events": [
{
"eventTime": "2025-10-13 13:46:07",
"eventTimeUtc": "2025-10-13T11:46:07.028470Z",
"lat": null,
"lon": null,
"locationContext": "Testbutikken",
"locationContextId": null,
"eventType": {
"apiKey": "001",
"description": "Meldt ankomst av pakke",
"i18nKey": "event.type.distr.import.edi.information.received"
},
"additionalInfo": null,
"eventGroup": {
"id": 1,
"name": "event.type.group.import"
},
"comChannelType": null,
"changeUserId": null,
"changeUsername": null,
"regSystem": {
"id": 1,
"name": "Beh. Engangslev."
},
"message": null,
"eventData": null
}
]
}
]
}
]
For a PUDO return nothing moves until the customer drops the parcel off, so expect a gap between booking and the first scan.
