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

# Fulfillment Services

> Register your app as a fulfillment provider so the platform shows tracking, attributes shipments, and routes fulfillment callbacks correctly.

A **fulfillment service** is a registry row that tells the platform
"this app handles shipping for this store". Registering one is
optional, but recommended for shipping apps because it:

1. Lets every Fulfillment row created by your app carry a `service_id`
   pointing back to you (audit + attribution).
2. Enables 3PL-style callbacks: the platform POSTs to your
   `callbackUrl` when an order is paid so you can pull labels
   automatically.
3. Surfaces your app's name on the order detail page next to the
   tracking number, instead of a generic carrier label.

## Register at install time

The canonical place to register is your OAuth handoff
([install-handoff](/getting-started/install-handoff)). After exchanging
the authorization code for an access token, list existing services and
create one only if your app isn't already registered (idempotent):

```js theme={null}
import {
  ensureFulfillmentService,
} from '@launchmystore/apps-shared';

const serviceId = await ensureFulfillmentService({
  accessToken,               // OAuth bearer for this store
  name: 'Your App Name',
  callbackUrl: `${APP_URL}/api/tracking`,
  trackingSupport: true,
  inventoryManagement: false,
  requiresShippingMethod: false,
});

// Cache on a shop metafield so subsequent fulfillment writes can
// attribute by service_id without a round-trip:
await setMetafield({
  accessToken,
  ownerType: 'shop',
  key: 'fulfillment_service_id',
  value: String(serviceId),
  type: 'single_line_text_field',
});
```

## Create Fulfillment Service

<ParamField path="POST /api/v1/fulfillment_services.json" />

### Body Parameters

<ParamField body="name" type="string" required>
  Display name (e.g. `"Shiprocket"`, `"ShipGlobal"`). Used on the order
  detail page next to tracking numbers.
</ParamField>

<ParamField body="callbackUrl" type="string" required>
  HTTPS URL the platform calls when fulfillment events occur on this
  store. Must be a valid URL.
</ParamField>

<ParamField body="tracking_support" type="boolean" default="true">
  Whether your app can provide tracking numbers.
</ParamField>

<ParamField body="inventory_management" type="boolean" default="false">
  Whether your app authoritatively manages inventory levels for this
  store (3PL-style).
</ParamField>

<ParamField body="requires_shipping_method" type="boolean" default="false">
  Whether your app needs the merchant to pre-select a shipping method
  before fulfilling.
</ParamField>

### Required scope

`write_orders`

## List Fulfillment Services

<ParamField path="GET /api/v1/fulfillment_services.json" />

Returns every fulfillment service registered for the calling store.
Use this to make registration idempotent — match on `name` before
creating a new row.

### Required scope

`read_orders`

## After registration

Once registered, every Fulfillment row your app creates via
[Create Fulfillment](/api-reference/fulfillments/create) should
include `service_id` set to the value returned at registration. The
platform uses that pointer for the FULFILLMENTS\_CREATE webhook
attribution and the order detail page UI.
