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

# Creating a shipment with service point delivery

**Service points**, also known as drop-off locations, are physical locations affiliated with one or more specific carriers. Parcels can be dropped off at these locations, and a driver will collect them and take them to be sorted at the carrier's sorting hub. Parcels can also be delivered to service points as an alternative to door-to-door delivery. A service point can be a local post office, a brick-and-mortar store, or a fuel station.

Service point delivery is an increasingly popular choice among e-commerce consumers, as it allows them to pick up their parcels at a time and location that are convenient to them. The customer can see when their parcel is ready for collection using the tracking number.

This tutorial walks through the complete API v3 flow for delivering a shipment to a service point: finding a suitable service point, checking that it's still available, selecting a compatible shipping option, and creating and announcing the shipment.

## Before you start

Service Points API v3 supports two ways to choose which carriers to search:

* use the carriers enabled in your [integration settings](https://app.sendcloud.com/v2/settings/integrations/manage)
* provide the carrier codes explicitly in the request

If you plan to use the carriers from your integration settings, make sure service points are enabled and the required carriers are configured for your integration:

1. In the Sendcloud platform, go to your [integration settings](https://app.sendcloud.com/v2/settings/integrations/manage)
2. Find your API integration and click **Configure**
3. Enable service point delivery
4. Enable the carriers you want to use for service point delivery and **save your changes**

<img src="https://mintcdn.com/sendcloud/bH_7gFwWAF2dSsyu/images/docs/service-points/enable-service-points-in-integration-settings.png?fit=max&auto=format&n=bH_7gFwWAF2dSsyu&q=85&s=29c6265e69eda263758ca13d99070dee" alt="Screenshot showing how to enable service points in the integration settings" width="914" height="1232" data-path="images/docs/service-points/enable-service-points-in-integration-settings.png" />

<Info>
  You can skip this configuration if you plan to search for service points by providing carrier codes explicitly.
</Info>

## Step 1: Find a service point

Start by searching for service points near the recipient using the [Retrieve a list of service points](/api/v3/service-points/retrieve-a-list-of-service-points) endpoint.

A country code is required, and you must choose how carriers are selected:

* Set `use_integration_carriers=true` to search using the carriers enabled in your integration settings. If you use this option, make sure service points and the required carriers are configured as described in [Before you start](#before-you-start)
* Provide one or more `carrier_code` parameters to search specific carriers directly. These carriers do not need to be enabled in your integration settings

<Warning>
  These two options are mutually exclusive: use either `use_integration_carriers` or `carrier_code`, but not both.
</Warning>

For example, to search using the carriers configured for your integration:

```http Example request method and URL theme={null}
GET https://panel.sendcloud.sc/api/v3/service-points?country_code=NL&address=Stadhuisplein%2010%2C%20Eindhoven&use_integration_carriers=true
```

To search specific carriers instead:

```http Example request method and URL theme={null}
GET https://panel.sendcloud.sc/api/v3/service-points?country_code=NL&address=Stadhuisplein%2010%2C%20Eindhoven&carrier_code=postnl&carrier_code=dhl
```

The `address` parameter is geocoded into a reference location, and the closest service points are returned first.
You can also provide the address as separate `address_*` parameters, or use `latitude` and `longitude` directly if you already know the delivery location's coordinates.

See the [Retrieve a list of service points](/api/v3/service-points/retrieve-a-list-of-service-points) endpoint for all supported search parameters.

<Info>
  If you only need a certain number of nearby service points, set `limit` to that number. Returning fewer results can
  improve request performance and make the service point selection flow more responsive.
</Info>

The closest matching service points are returned first:

```json Example response body theme={null}
{
  "data": {
    "results": [
      {
        "id": 1000001,
        "name": "Stadhuisplein Parcel Shop",
        "carrier": {
          "code": "postnl",
          "name": "PostNL",
          "logo_url": <...>,
          "icon_url": <...>
        },
        "carrier_service_point_id": "NL-00001",
        "address": {
          "street": "Stadhuisplein",
          "house_number": "1",
          "postal_code": "5611EM",
          "city": "Eindhoven",
          "country_code": "NL"
        },
        "position": {
          "latitude": 51.438022,
          "longitude": 5.478543
        },
        "opening_times": <...>,
        "is_open_tomorrow": true,
        "next_open_at": "2026-03-11T09:00:00+01:00",
        "is_expired": false,
        "distance": 85
      },
      <...>
    ],
    "geocoding": {
      "status": "matched",
      "precision": "house_number",
      "formatted_address": "Stadhuisplein 10, 5611 EM Eindhoven, Nederland"
    }
  }
}
```

When searching by address, check `data.geocoding` to see how the address was resolved.
A `partially_matched` result can still return service points, while `precision` indicates how closely the resolved location matches the address you provided.

Show the returned service points to the recipient, for example on a map or in a list, and let them choose one.
Keep the selected service point id, as you'll need it in the following steps.

### No service points found

If no service points are returned, check `data.geocoding.status` first.
If the address was `matched` or `partially_matched`, the location was found successfully, but there are no service points matching the current search.

```json Example response - no service points nearby theme={null}
{
  "data": {
    "results": [],
    "geocoding": {
      "status": "matched",
      "precision": "house_number",
      "formatted_address": "Stadhuisplein 10, 5611 EM Eindhoven, Nederland"
    }
  }
}
```

In this case, try making the search less restrictive. You can increase the `radius` or expand the bounding box, or remove these limits entirely to return the closest matching service points regardless of how far away they are.

If `data.geocoding.status` is `not_found`, the address itself could not be resolved:

```json Example response - address not found theme={null}
{
  "data": {
    "results": [],
    "geocoding": {
      "status": "not_found",
      "precision": null,
      "formatted_address": null
    }
  }
}
```

When this happens in an interactive flow, such as checkout, you can ask the customer to review the delivery address and try again.

## Step 2: Check the service point is still available

Service point availability can change over time. The search endpoint may return service points based on recently updated data, but that does not guarantee they are still available for delivery.

Before creating the shipment, check the selected service point using the [Check availability of a service point](/api/v3/service-points/check-availability-of-a-service-point) endpoint.

Use the service point `id` selected in [Step 1](#step-1-find-a-service-point):

```http Example request method and URL theme={null}
POST https://panel.sendcloud.sc/api/v3/service-points/1000001/check-availability
```

```json Example response body theme={null}
{
  "data": {
    "is_available": true
  }
}
```

The way availability is determined depends on the carrier. For some carriers, this involves a live check with the carrier.
For others, the result is based on the best available information at the time of the request.

If `is_available` is `false`, do not continue with that service point. Your flow should select a different service point before creating the shipment.

## Step 3: Find a shipping option

Now that you have selected an available service point, use the [Return a list of available shipping options](/api/v3/shipping-options/return-a-list-of-available-shipping-options) endpoint to find shipping options that can deliver the shipment there.

Include the selected service point `id` from [Step 1](#step-1-find-a-service-point) as `to_service_point.id`, together with the shipment details that affect shipping option availability, such as the origin, destination, and parcel weight.

```http Example request method and URL theme={null}
POST https://panel.sendcloud.sc/api/v3/shipping-options
```

```json Example request body theme={null}
{
  "from_address": {
    "country_code": "NL",
    "postal_code": "1000AA",
    "city": "Amsterdam"
  },
  "to_address": {
    "country_code": "NL",
    "postal_code": "5611EM",
    "city": "Eindhoven"
  },
  "to_service_point": {
    "id": "1000001"
  },
  "parcels": [
    {
      "weight": {
        "value": "1.500",
        "unit": "kg"
      }
    }
  ]
}
```

The response contains the shipping options available for the shipment and selected service point:

```json Example response body theme={null}
{
  "data": [
    {
      "code": "postnl:pakjegemak",
      "name": "PostNL service point",
      "carrier": {
        "code": "postnl",
        "name": "PostNL"
      },
      <...>
    }
  ]
}
```

Choose one of the returned shipping options and keep its code. We'll use `postnl:pakjegemak` when creating the shipment in the next step.

See [Shipping options & quotes](/docs/shipments/shipping-options-and-quotes) for more on filtering options, calculating quotes, and shipping functionalities.

### Finding a shipping option before service point selection

Some flows retrieve the available delivery options before a specific pickup location has been selected.
In that case, omit `to_service_point` and filter shipping options using `functionalities.last_mile` instead.

For example, to find shipping options that support service point delivery:

```json Example request body theme={null}
{
  "from_address": {
    "country_code": "NL",
    "postal_code": "1000AA",
    "city": "Amsterdam"
  },
  "to_address": {
    "country_code": "NL",
    "postal_code": "5611EM",
    "city": "Eindhoven"
  },
  "functionalities": {
    "last_mile": "service_point"
  },
  "parcels": [
    {
      "weight": {
        "value": "1.500",
        "unit": "kg"
      }
    }
  ]
}
```

This returns shipping options that support service point delivery without restricting the request to a specific service point.

<Info>
  `service_point` is one of the supported `last_mile` values. Other values can be used for different delivery types,
  including locker delivery and options that support either lockers or service points. See the [Shipping Options API
  reference](/api/v3/shipping-options/return-a-list-of-available-shipping-options) for the available `last_mile` values.
</Info>

## Step 4: Create and announce the shipment

With an available service point and a compatible shipping option selected, you can now create and announce the shipment using the [Create and announce a shipment synchronously](/api/v3/shipments/create-and-announce-a-shipment-synchronously) endpoint.

Include the service point `id` from [Step 1](#step-1-find-a-service-point) in `to_service_point.id`, and use the shipping option `code` from [Step 3](#step-3-find-a-shipping-option) in `ship_with.properties.shipping_option_code`.

```http Example request method and URL theme={null}
POST https://panel.sendcloud.sc/api/v3/shipments/announce
```

```json Example request body theme={null}
{
  "to_address": {
    "name": "John Doe",
    "address_line_1": "Stadhuisplein",
    "house_number": "10",
    "postal_code": "5611EM",
    "city": "Eindhoven",
    "country_code": "NL",
    "email": "john.doe@example.com"
  },
  "from_address": {
    "sender_address_id": 42
  },
  "to_service_point": {
    "id": "1000001"
  },
  "ship_with": {
    "type": "shipping_option_code",
    "properties": {
      "shipping_option_code": "postnl:pakjegemak"
    }
  },
  "parcels": [
    {
      "weight": {
        "value": "1.500",
        "unit": "kg"
      }
    }
  ]
}
```

The response includes the created shipment, the service point it will be delivered to, and a link to the label:

```json Example response body theme={null}
{
  "data": {
    "id": "facade00-0000-4000-a000-000000000000",
    "ship_with": {
      "type": "shipping_option_code",
      "properties": {
        "shipping_option_code": "postnl:pakjegemak",
        "contract_id": 101
      }
    },
    "to_service_point": {
      "id": 1000001,
      "carrier_service_point_id": "12345"
    },
    "carrier": {
      "code": "postnl",
      "name": "PostNL"
    },
    <...>
  }
}
```

See [Create a shipment](/docs/shipments/create-a-shipment) for the full request schema, error handling, and advanced options like customs and insurance.
