Files
medusa-store/www/apps/docs/content/references/fulfillment/classes/fulfillment.AbstractFulfillmentService.mdx
Shahed Nasser bb87db8342 docs: prep for v2 documentation (#6710)
This PR includes documentation that preps for v2 docs (but doesn't introduce new docs).

_Note: The number of file changes in the PR is due to find-and-replace within the `references` which is unavoidable. Let me know if I should move it to another PR._

## Changes

- Change Medusa version in base OAS used for v2.
- Fix to docblock generator related to not catching all path parameters.
- Added typedoc plugin that generates ER Diagrams, which will be used specifically for data model references in commerce modules.
- Changed OAS tool to output references in `www/apps/api-reference/specs-v2` directory when the `--v2` option is used.
- Added a version switcher to the API reference to switch between V1 and V2. This switcher is enabled by an environment variable, so it won't be visible/usable at the moment.
- Upgraded docusaurus to v3.0.1
- Added new Vale rules to ensure correct spelling of Medusa Admin and module names.
- Added new components to the `docs-ui` package that will be used in future documentation changes.
2024-03-18 07:47:35 +00:00

473 lines
65 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
displayed_sidebar: modules
slug: /modules/carts-and-checkout/backend/add-fulfillment-provider
---
import TypeList from "@site/src/components/TypeList"
# How to Create a Fulfillment Provider
In this document, youll learn how to create a fulfillment provider in the Medusa backend and the methods you must implement in it. If youre unfamiliar with the Shipping architecture in Medusa, make sure to [check out the overview first](https://docs.medusajs.com/modules/carts-and-checkout/shipping).
## Overview
A fulfillment provider is the shipping provider used to fulfill orders and deliver them to customers. An example of a fulfillment provider is FedEx.
By default, a Medusa Backend has a `manual` fulfillment provider which has minimal implementation. It allows you to accept orders and fulfill them manually. However, you can integrate any fulfillment provider into Medusa, and your fulfillment provider can interact with third-party shipping providers.
A fulfillment provider is a service that extends the `AbstractFulfillmentService` and implements its methods. So, adding a fulfillment provider is as simple as creating a service file in `src/services`.
The file's name is the fulfillment provider's class name as a slug and without the word `Service`. For example, if you're creating a `MyFulfillmentService` class, the file name is `src/services/my-fulfillment.ts`.
```ts title=src/services/my-fulfillment.ts
import { AbstractFulfillmentService } from "@medusajs/medusa"
class MyFulfillmentService extends AbstractFulfillmentService {
// methods here...
}
export default MyFulfillmentService
```
---
## Identifier Property
The `FulfillmentProvider` entity has 2 properties: `identifier` and `is_installed`. The `identifier` property in the fulfillment provider service is used when the fulfillment provider is added to the database.
The value of this property is also used to reference the fulfillment provider throughout Medusa. For example, it is used to [add a fulfillment provider](https://docs.medusajs.com/api/admin#regions\_postregionsregionfulfillmentproviders) to a region.
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
static identifier = "my-fulfillment"
// ...
}
```
---
## constructor
You can use the `constructor` of your fulfillment provider to access the different services in Medusa through dependency injection.
You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party providers APIs, you can initialize it in the constructor and use it in other methods in the service.
Additionally, if youre creating your fulfillment provider as an external plugin to be installed on any Medusa backend and you want to access the options added for the plugin, you can access it in the constructor.
### Example
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
constructor(container, options) {
super(container)
// you can access options here
// you can also initialize a client that
// communicates with a third-party service.
this.client = new Client(options)
}
// ...
}
```
### Parameters
<TypeList types={[{"name":"container","type":"`Record<string, unknown>`","description":"An instance of `MedusaContainer` that allows you to access other resources, such as services, in your Medusa backend.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"config","type":"`Record<string, unknown>`","description":"If this fulfillment provider is created in a plugin, the plugin's options are passed in this parameter.","optional":true,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="new AbstractFulfillmentService"/>
___
## Methods
### getFulfillmentOptions
This method is used when retrieving the list of fulfillment options available in a region, particularly by the [List Fulfillment Options API Route](https://docs.medusajs.com/api/admin#regions\_getregionsregionfulfillmentoptions).
For example, if youre integrating UPS as a fulfillment provider, you might support two fulfillment options: UPS Express Shipping and UPS Access Point. Each of these options can have different data associated with them.
#### Example
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async getFulfillmentOptions(): Promise<any[]> {
return [
{
id: "my-fulfillment",
},
{
id: "my-fulfillment-dynamic",
},
]
}
}
```
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;any[]&#62;","optional":false,"defaultValue":"","description":"The list of fulfillment options. These options don't have any required format. Later on, these options can be used when creating a shipping option,\nsuch as when using the [Create Shipping Option API Route](https://docs.medusajs.com/api/admin#shipping-options\\_postshippingoptions). The chosen fulfillment option, which is one of the\nitems in the array returned by this method, will be set in the `data` object of the shipping option.","expandable":false,"children":[{"name":"any[]","type":"`any`[]","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="getFulfillmentOptions"/>
### validateFulfillmentData
This method is called when a shipping method is created. This typically happens when the customer chooses a shipping option during checkout, when a shipping method is created
for an order return, or in other similar cases. The shipping option and its data are validated before the shipping method is created.
You can use the provided parameters to validate the chosen shipping option. For example, you can check if the `data` object passed as a second parameter includes all data needed to
fulfill the shipment later on.
If any of the data is invalid, you can throw an error. This error will stop Medusa from creating a shipping method and the error message will be returned as a result of the API Route.
#### Example
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async validateFulfillmentData(
optionData: Record<string, unknown>,
data: Record<string, unknown>,
cart: Cart
): Promise<Record<string, unknown>> {
if (data.id !== "my-fulfillment") {
throw new Error("invalid data")
}
return {
...data,
}
}
}
```
#### Parameters
<TypeList types={[{"name":"optionData","type":"[ShippingOptionData](../../medusa/types/medusa.ShippingOptionData.mdx)","description":"The data object of the shipping option selected when creating the shipping method.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"data","type":"[FulfillmentProviderData](../../medusa/types/medusa.FulfillmentProviderData.mdx)","description":"The `data` object passed in the body of the request.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"cart","type":"[Cart](../../entities/classes/entities.Cart.mdx)","description":"The customer's cart details. It may be empty if the shipping method isn't associated with a cart, such as when it's associated with a claim.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"id","type":"`string`","description":"The cart's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"created_at","type":"`Date`","description":"The date with timezone at which the resource was created.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"updated_at","type":"`Date`","description":"The date with timezone at which the resource was updated.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"deleted_at","type":"`null` \\| `Date`","description":"The date with timezone at which the resource was deleted.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"object","type":"`\"cart\"`","description":"","optional":false,"defaultValue":"\"cart\"","expandable":false,"children":[]},{"name":"email","type":"`string`","description":"The email associated with the cart","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"billing_address_id","type":"`string`","description":"The billing address's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"billing_address","type":"[Address](../../entities/classes/entities.Address.mdx)","description":"The details of the billing address associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_address_id","type":"`string`","description":"The shipping address's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"shipping_address","type":"`null` \\| [Address](../../entities/classes/entities.Address.mdx)","description":"The details of the shipping address associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"items","type":"[LineItem](../../entities/classes/entities.LineItem.mdx)[]","description":"The line items added to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"region_id","type":"`string`","description":"The region's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"region","type":"[Region](../../entities/classes/entities.Region.mdx)","description":"The details of the region associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"discounts","type":"[Discount](../../entities/classes/entities.Discount.mdx)[]","description":"An array of details of all discounts applied to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"gift_cards","type":"[GiftCard](../../entities/classes/entities.GiftCard.mdx)[]","description":"An array of details of all gift cards applied to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"customer_id","type":"`string`","description":"The customer's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"customer","type":"[Customer](../../entities/classes/entities.Customer.mdx)","description":"The details of the customer the cart belongs to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payment_session","type":"`null` \\| [PaymentSession](../../entities/classes/entities.PaymentSession.mdx)","description":"The details of the selected payment session in the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payment_sessions","type":"[PaymentSession](../../entities/classes/entities.PaymentSession.mdx)[]","description":"The details of all payment sessions created on the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payment_id","type":"`string`","description":"The payment's ID if available","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"payment","type":"[Payment](../../entities/classes/entities.Payment.mdx)","description":"The details of the payment associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_methods","type":"[ShippingMethod](../../entities/classes/entities.ShippingMethod.mdx)[]","description":"The details of the shipping methods added to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"type","type":"[CartType](../../entities/enums/entities.CartType.mdx)","description":"The cart's type.","optional":false,"defaultValue":"default","expandable":false,"children":[]},{"name":"completed_at","type":"`Date`","description":"The date with timezone at which the cart was completed.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"payment_authorized_at","type":"`Date`","description":"The date with timezone at which the payment was authorized.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"idempotency_key","type":"`string`","description":"Randomly generated key used to continue the completion of a cart in case of failure.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"context","type":"`Record<string, unknown>`","description":"The context of the cart which can include info like IP or user agent.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"metadata","type":"`Record<string, unknown>`","description":"An optional key-value map with additional details","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channel_id","type":"`null` \\| `string`","description":"The sales channel ID the cart is associated with.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channel","type":"[SalesChannel](../../entities/classes/entities.SalesChannel.mdx)","description":"The details of the sales channel associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"sales_channels","type":"[SalesChannel](../../entities/classes/entities.SalesChannel.mdx)[]","description":"The associated sales channels.","optional":true,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_total","type":"`number`","description":"The total of shipping","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"discount_total","type":"`number`","description":"The total of discount rounded","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"raw_discount_total","type":"`number`","description":"The total of discount","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"item_tax_total","type":"`null` \\| `number`","description":"The total of items with taxes","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"shipping_tax_total","type":"`null` \\| `number`","description":"The total of shipping with taxes","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"tax_total","type":"`null` \\| `number`","description":"The total of tax","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"refunded_total","type":"`number`","description":"The total amount refunded if the order associated with this cart is returned.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"total","type":"`number`","description":"The total amount of the cart","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"subtotal","type":"`number`","description":"The subtotal of the cart","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"refundable_amount","type":"`number`","description":"The amount that can be refunded","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_total","type":"`number`","description":"The total of gift cards","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_tax_total","type":"`number`","description":"The total of gift cards with taxes","optional":true,"defaultValue":"","expandable":false,"children":[]}]}]} sectionTitle="validateFulfillmentData"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;Record&#60;string, unknown&#62;&#62;","optional":false,"defaultValue":"","description":"The data that will be stored in the `data` property of the shipping method to be created.\nMake sure the value you return contains everything you need to fulfill the shipment later on. The returned value may also be used to calculate the price of the shipping method\nif it doesn't have a set price. It will be passed along to the [calculatePrice](fulfillment.AbstractFulfillmentService.mdx#calculateprice) method.","expandable":false,"children":[{"name":"Record","type":"`Record<string, unknown>`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="validateFulfillmentData"/>
### validateOption
Once the admin creates the shipping option, the data of the shipping option will be validated first using this method. This method is called when the [Create Shipping Option API Route](https://docs.medusajs.com/api/admin#shipping-options\_postshippingoptions) is used.
#### Example
For example, you can use this method to ensure that the `id` in the `data` object is correct:
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async validateOption(
data: Record<string, unknown>
): Promise<boolean> {
return data.id == "my-fulfillment"
}
}
```
#### Parameters
<TypeList types={[{"name":"data","type":"[ShippingOptionData](../../medusa/types/medusa.ShippingOptionData.mdx)","description":"the data object that is sent in the body of the request, basically, the data object of the shipping option. You can use this data to validate the shipping option before it is saved.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="validateOption"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;boolean&#62;","optional":false,"defaultValue":"","description":"Whether the fulfillment option is valid. If the returned value is false, an error is thrown and the shipping option will not be saved.","expandable":false,"children":[{"name":"boolean","type":"`boolean`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="validateOption"/>
### canCalculate
This method is used to determine whether a shipping option is calculated dynamically or flat rate. It is called if the `price_type` of the shipping option being created is set to calculated.
#### Example
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async canCalculate(
data: Record<string, unknown>
): Promise<boolean> {
return data.id === "my-fulfillment-dynamic"
}
}
```
#### Parameters
<TypeList types={[{"name":"data","type":"[ShippingOptionData](../../medusa/types/medusa.ShippingOptionData.mdx)","description":"The `data` object of the shipping option being created. You can use this data to determine whether the shipping option should be calculated or not.\nThis is useful if the fulfillment provider you are integrating has both flat rate and dynamically priced fulfillment options.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="canCalculate"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;boolean&#62;","optional":false,"defaultValue":"","description":"If this method returns `true`, that means that the price can be calculated dynamically and the shipping option can have the `price_type` set to calculated.\nThe amount property of the shipping option will then be set to null. The amount will be created later when the shipping method is created on checkout using the [calculatePrice](fulfillment.AbstractFulfillmentService.mdx#calculateprice) method.\nIf the method returns `false`, an error is thrown as it means the selected shipping option is invalid and it can only have the `flat_rate` price type.","expandable":false,"children":[{"name":"boolean","type":"`boolean`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="canCalculate"/>
### calculatePrice
This method is used in different places, including:
1. When the shipping options for a cart are retrieved during checkout. If a shipping option has their `price_type` set to calculated, this method is used to set the amount of the returned shipping option.
2. When a shipping method is created. If the shipping option associated with the method has their `price_type` set to `calculated`, this method is used to set the `price` attribute of the shipping method in the database.
3. When the cart's totals are calculated.
#### Example
An example of calculating the price based on some custom logic:
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async calculatePrice(
optionData: Record<string, unknown>,
data: Record<string, unknown>,
cart: Cart
): Promise<number> {
return cart.items.length * 1000
}
}
```
If your fulfillment provider does not provide any dynamically calculated rates you can return any static value or throw an error. For example:
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async calculatePrice(
optionData: Record<string, unknown>,
data: Record<string, unknown>,
cart: Cart
): Promise<number> {
throw new Error("Method not implemented.")
}
}
```
#### Parameters
<TypeList types={[{"name":"optionData","type":"[ShippingOptionData](../../medusa/types/medusa.ShippingOptionData.mdx)","description":"The `data` object of the selected shipping option.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"data","type":"[FulfillmentProviderData](../../medusa/types/medusa.FulfillmentProviderData.mdx)","description":"A `data` object that is different based on the context it's used in:\n\n1. If the price is being calculated for the list of shipping options available for a cart, it's the `data` object of the shipping option.\n2. If the price is being calculated when the shipping method is being created, it's the data returned by the [validateFulfillmentData](fulfillment.AbstractFulfillmentService.mdx#validatefulfillmentdata) method used during the shipping method creation.\n3. If the price is being calculated while calculating the cart's totals, it will be the data object of the cart's shipping method.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"cart","type":"[Cart](../../entities/classes/entities.Cart.mdx)","description":"Either the Cart or the Order object.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"id","type":"`string`","description":"The cart's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"created_at","type":"`Date`","description":"The date with timezone at which the resource was created.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"updated_at","type":"`Date`","description":"The date with timezone at which the resource was updated.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"deleted_at","type":"`null` \\| `Date`","description":"The date with timezone at which the resource was deleted.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"object","type":"`\"cart\"`","description":"","optional":false,"defaultValue":"\"cart\"","expandable":false,"children":[]},{"name":"email","type":"`string`","description":"The email associated with the cart","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"billing_address_id","type":"`string`","description":"The billing address's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"billing_address","type":"[Address](../../entities/classes/entities.Address.mdx)","description":"The details of the billing address associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_address_id","type":"`string`","description":"The shipping address's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"shipping_address","type":"`null` \\| [Address](../../entities/classes/entities.Address.mdx)","description":"The details of the shipping address associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"items","type":"[LineItem](../../entities/classes/entities.LineItem.mdx)[]","description":"The line items added to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"region_id","type":"`string`","description":"The region's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"region","type":"[Region](../../entities/classes/entities.Region.mdx)","description":"The details of the region associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"discounts","type":"[Discount](../../entities/classes/entities.Discount.mdx)[]","description":"An array of details of all discounts applied to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"gift_cards","type":"[GiftCard](../../entities/classes/entities.GiftCard.mdx)[]","description":"An array of details of all gift cards applied to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"customer_id","type":"`string`","description":"The customer's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"customer","type":"[Customer](../../entities/classes/entities.Customer.mdx)","description":"The details of the customer the cart belongs to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payment_session","type":"`null` \\| [PaymentSession](../../entities/classes/entities.PaymentSession.mdx)","description":"The details of the selected payment session in the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payment_sessions","type":"[PaymentSession](../../entities/classes/entities.PaymentSession.mdx)[]","description":"The details of all payment sessions created on the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payment_id","type":"`string`","description":"The payment's ID if available","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"payment","type":"[Payment](../../entities/classes/entities.Payment.mdx)","description":"The details of the payment associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_methods","type":"[ShippingMethod](../../entities/classes/entities.ShippingMethod.mdx)[]","description":"The details of the shipping methods added to the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"type","type":"[CartType](../../entities/enums/entities.CartType.mdx)","description":"The cart's type.","optional":false,"defaultValue":"default","expandable":false,"children":[]},{"name":"completed_at","type":"`Date`","description":"The date with timezone at which the cart was completed.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"payment_authorized_at","type":"`Date`","description":"The date with timezone at which the payment was authorized.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"idempotency_key","type":"`string`","description":"Randomly generated key used to continue the completion of a cart in case of failure.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"context","type":"`Record<string, unknown>`","description":"The context of the cart which can include info like IP or user agent.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"metadata","type":"`Record<string, unknown>`","description":"An optional key-value map with additional details","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channel_id","type":"`null` \\| `string`","description":"The sales channel ID the cart is associated with.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channel","type":"[SalesChannel](../../entities/classes/entities.SalesChannel.mdx)","description":"The details of the sales channel associated with the cart.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"sales_channels","type":"[SalesChannel](../../entities/classes/entities.SalesChannel.mdx)[]","description":"The associated sales channels.","optional":true,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_total","type":"`number`","description":"The total of shipping","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"discount_total","type":"`number`","description":"The total of discount rounded","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"raw_discount_total","type":"`number`","description":"The total of discount","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"item_tax_total","type":"`null` \\| `number`","description":"The total of items with taxes","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"shipping_tax_total","type":"`null` \\| `number`","description":"The total of shipping with taxes","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"tax_total","type":"`null` \\| `number`","description":"The total of tax","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"refunded_total","type":"`number`","description":"The total amount refunded if the order associated with this cart is returned.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"total","type":"`number`","description":"The total amount of the cart","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"subtotal","type":"`number`","description":"The subtotal of the cart","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"refundable_amount","type":"`number`","description":"The amount that can be refunded","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_total","type":"`number`","description":"The total of gift cards","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_tax_total","type":"`number`","description":"The total of gift cards with taxes","optional":true,"defaultValue":"","expandable":false,"children":[]}]}]} sectionTitle="calculatePrice"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;number&#62;","optional":false,"defaultValue":"","description":"Used to set the price of the shipping method or option, based on the context the method is used in.","expandable":false,"children":[{"name":"number","type":"`number`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="calculatePrice"/>
### createFulfillment
This method is used when a fulfillment is created for an order, a claim, or a swap.
#### Example
Here is a basic implementation of `createFulfillment` for a fulfillment provider that does not interact with any third-party provider to create the fulfillment:
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async createFulfillment(
data: Record<string, unknown>,
items: LineItem[],
order: Order,
fulfillment: Fulfillment
) {
// No data is being sent anywhere
// No data to be stored in the fulfillment's data object
return {}
}
}
```
#### Parameters
<TypeList types={[{"name":"data","type":"[ShippingMethodData](../../medusa/types/medusa.ShippingMethodData.mdx)","description":"The `data` object of the shipping method associated with the resource, such as the order.\nYou can use it to access the data specific to the shipping option. This is based on your implementation of previous methods.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"items","type":"[LineItem](../../entities/classes/entities.LineItem.mdx)[]","description":"The line items in the order to be fulfilled. The admin can choose all or some of the items to fulfill.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"id","type":"`string`","description":"The line item's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"created_at","type":"`Date`","description":"The date with timezone at which the resource was created.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"updated_at","type":"`Date`","description":"The date with timezone at which the resource was updated.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"cart_id","type":"`string`","description":"The ID of the cart that the line item may belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"cart","type":"[Cart](../../entities/classes/entities.Cart.mdx)","description":"The details of the cart that the line item may belongs to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"order_id","type":"`null` \\| `string`","description":"The ID of the order that the line item may belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"order","type":"[Order](../../entities/classes/entities.Order.mdx)","description":"The details of the order that the line item may belongs to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"swap_id","type":"`string`","description":"The ID of the swap that the line item may belong to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"swap","type":"[Swap](../../entities/classes/entities.Swap.mdx)","description":"The details of the swap that the line item may belong to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"claim_order_id","type":"`string`","description":"The ID of the claim that the line item may belong to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"claim_order","type":"[ClaimOrder](../../entities/classes/entities.ClaimOrder.mdx)","description":"The details of the claim that the line item may belong to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"tax_lines","type":"[LineItemTaxLine](../../entities/classes/entities.LineItemTaxLine.mdx)[]","description":"The details of the item's tax lines.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"adjustments","type":"[LineItemAdjustment](../../entities/classes/entities.LineItemAdjustment.mdx)[]","description":"The details of the item's adjustments, which are available when a discount is applied on the item.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"title","type":"`string`","description":"The title of the Line Item.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"description","type":"`null` \\| `string`","description":"A more detailed description of the contents of the Line Item.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"thumbnail","type":"`null` \\| `string`","description":"A URL string to a small image of the contents of the Line Item.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"is_return","type":"`boolean`","description":"Is the item being returned","optional":false,"defaultValue":"false","expandable":false,"children":[]},{"name":"is_giftcard","type":"`boolean`","description":"Flag to indicate if the Line Item is a Gift Card.","optional":false,"defaultValue":"false","expandable":false,"children":[]},{"name":"should_merge","type":"`boolean`","description":"Flag to indicate if new Line Items with the same variant should be merged or added as an additional Line Item.","optional":false,"defaultValue":"true","expandable":false,"children":[]},{"name":"allow_discounts","type":"`boolean`","description":"Flag to indicate if the Line Item should be included when doing discount calculations.","optional":false,"defaultValue":"true","expandable":false,"children":[]},{"name":"has_shipping","type":"`null` \\| `boolean`","description":"Flag to indicate if the Line Item has fulfillment associated with it.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"unit_price","type":"`number`","description":"The price of one unit of the content in the Line Item. This should be in the currency defined by the Cart/Order/Swap/Claim that the Line Item belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"variant_id","type":"`null` \\| `string`","description":"The id of the Product Variant contained in the Line Item.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"variant","type":"[ProductVariant](../../entities/classes/entities.ProductVariant.mdx)","description":"The details of the product variant that this item was created from.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"product_id","type":"`null` \\| `string`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"quantity","type":"`number`","description":"The quantity of the content in the Line Item.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"fulfilled_quantity","type":"`null` \\| `number`","description":"The quantity of the Line Item that has been fulfilled.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"returned_quantity","type":"`null` \\| `number`","description":"The quantity of the Line Item that has been returned.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"shipped_quantity","type":"`null` \\| `number`","description":"The quantity of the Line Item that has been shipped.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"metadata","type":"`Record<string, unknown>`","description":"An optional key-value map with additional details","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"includes_tax","type":"`boolean`","description":"Indicates if the line item unit\\_price include tax","optional":false,"defaultValue":"false","expandable":false,"featureFlag":"tax_inclusive_pricing","children":[]},{"name":"original_item_id","type":"`null` \\| `string`","description":"The ID of the original line item. This is useful if the line item belongs to a resource that references an order, such as a return or an order edit.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"order_edit_id","type":"`null` \\| `string`","description":"The ID of the order edit that the item may belong to.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"order_edit","type":"`null` \\| [OrderEdit](../../entities/classes/entities.OrderEdit.mdx)","description":"The details of the order edit.","optional":true,"defaultValue":"","expandable":true,"children":[]},{"name":"refundable","type":"`null` \\| `number`","description":"The amount that can be refunded from the given Line Item. Takes taxes and discounts into consideration.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"subtotal","type":"`null` \\| `number`","description":"The subtotal of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"tax_total","type":"`null` \\| `number`","description":"The total of tax of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"total","type":"`null` \\| `number`","description":"The total amount of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"original_total","type":"`null` \\| `number`","description":"The original total amount of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"original_tax_total","type":"`null` \\| `number`","description":"The original tax total amount of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"discount_total","type":"`null` \\| `number`","description":"The total of discount of the line item rounded","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"raw_discount_total","type":"`null` \\| `number`","description":"The total of discount of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_total","type":"`null` \\| `number`","description":"The total of the gift card of the line item","optional":true,"defaultValue":"","expandable":false,"children":[]}]},{"name":"order","type":"[Order](../../entities/classes/entities.Order.mdx)","description":"The details of the created resource, which is either an order, a claim, or a swap:\n- If the resource the fulfillment is being created for is a claim, the `is_claim` property in the object will be `true`.\n- If the resource the fulfillment is being created for is a swap, the `is_swap` property in the object will be `true`.\n- Otherwise, the resource is an order.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"id","type":"`string`","description":"The order's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"created_at","type":"`Date`","description":"The date with timezone at which the resource was created.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"updated_at","type":"`Date`","description":"The date with timezone at which the resource was updated.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"object","type":"`\"order\"`","description":"","optional":false,"defaultValue":"\"order\"","expandable":false,"children":[]},{"name":"status","type":"[OrderStatus](../../entities/enums/entities.OrderStatus.mdx)","description":"The order's status","optional":false,"defaultValue":"pending","expandable":false,"children":[]},{"name":"fulfillment_status","type":"[FulfillmentStatus](../../entities/enums/entities.FulfillmentStatus.mdx)","description":"The order's fulfillment status","optional":false,"defaultValue":"not_fulfilled","expandable":false,"children":[]},{"name":"payment_status","type":"[PaymentStatus](../../entities/enums/entities.PaymentStatus.mdx)","description":"The order's payment status","optional":false,"defaultValue":"not_paid","expandable":false,"children":[]},{"name":"display_id","type":"`number`","description":"The order's display ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"cart_id","type":"`string`","description":"The ID of the cart associated with the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"cart","type":"[Cart](../../entities/classes/entities.Cart.mdx)","description":"The details of the cart associated with the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"customer_id","type":"`string`","description":"The ID of the customer associated with the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"customer","type":"[Customer](../../entities/classes/entities.Customer.mdx)","description":"The details of the customer associated with the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"email","type":"`string`","description":"The email associated with the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"billing_address_id","type":"`string`","description":"The ID of the billing address associated with the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"billing_address","type":"[Address](../../entities/classes/entities.Address.mdx)","description":"The details of the billing address associated with the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_address_id","type":"`string`","description":"The ID of the shipping address associated with the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"shipping_address","type":"[Address](../../entities/classes/entities.Address.mdx)","description":"The details of the shipping address associated with the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"region_id","type":"`string`","description":"The ID of the region this order was created in.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"region","type":"[Region](../../entities/classes/entities.Region.mdx)","description":"The details of the region this order was created in.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"currency_code","type":"`string`","description":"The 3 character currency code that is used in the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"currency","type":"[Currency](../../entities/classes/entities.Currency.mdx)","description":"The details of the currency used in the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"tax_rate","type":"`null` \\| `number`","description":"The order's tax rate","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"discounts","type":"[Discount](../../entities/classes/entities.Discount.mdx)[]","description":"The details of the discounts applied on the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"gift_cards","type":"[GiftCard](../../entities/classes/entities.GiftCard.mdx)[]","description":"The details of the gift card used in the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_methods","type":"[ShippingMethod](../../entities/classes/entities.ShippingMethod.mdx)[]","description":"The details of the shipping methods used in the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"payments","type":"[Payment](../../entities/classes/entities.Payment.mdx)[]","description":"The details of the payments used in the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"fulfillments","type":"[Fulfillment](../../entities/classes/entities.Fulfillment.mdx)[]","description":"The details of the fulfillments created for the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"returns","type":"[Return](../../entities/classes/entities.Return.mdx)[]","description":"The details of the returns created for the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"claims","type":"[ClaimOrder](../../entities/classes/entities.ClaimOrder.mdx)[]","description":"The details of the claims created for the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"refunds","type":"[Refund](../../entities/classes/entities.Refund.mdx)[]","description":"The details of the refunds created for the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"swaps","type":"[Swap](../../entities/classes/entities.Swap.mdx)[]","description":"The details of the swaps created for the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"draft_order_id","type":"`string`","description":"The ID of the draft order this order was created from.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"draft_order","type":"[DraftOrder](../../entities/classes/entities.DraftOrder.mdx)","description":"The details of the draft order this order was created from.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"edits","type":"[OrderEdit](../../entities/classes/entities.OrderEdit.mdx)[]","description":"The details of the order edits done on the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"items","type":"[LineItem](../../entities/classes/entities.LineItem.mdx)[]","description":"The details of the line items that belong to the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"gift_card_transactions","type":"[GiftCardTransaction](../../entities/classes/entities.GiftCardTransaction.mdx)[]","description":"The gift card transactions made in the order.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"canceled_at","type":"`Date`","description":"The date the order was canceled on.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"metadata","type":"`Record<string, unknown>`","description":"An optional key-value map with additional details","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"no_notification","type":"`boolean`","description":"Flag for describing whether or not notifications related to this should be send.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"idempotency_key","type":"`string`","description":"Randomly generated key used to continue the processing of the order in case of failure.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"external_id","type":"`null` \\| `string`","description":"The ID of an external order.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channel_id","type":"`null` \\| `string`","description":"The ID of the sales channel this order belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channel","type":"[SalesChannel](../../entities/classes/entities.SalesChannel.mdx)","description":"The details of the sales channel this order belongs to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"shipping_total","type":"`number`","description":"The total of shipping","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"shipping_tax_total","type":"`null` \\| `number`","description":"The tax total applied on shipping","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"discount_total","type":"`number`","description":"The total of discount rounded","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"raw_discount_total","type":"`number`","description":"The total of discount","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"item_tax_total","type":"`null` \\| `number`","description":"The tax total applied on items","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"tax_total","type":"`null` \\| `number`","description":"The total of tax","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"refunded_total","type":"`number`","description":"The total amount refunded if the order is returned.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"total","type":"`number`","description":"The total amount of the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"subtotal","type":"`number`","description":"The subtotal of the order","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"paid_total","type":"`number`","description":"The total amount paid","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"refundable_amount","type":"`number`","description":"The amount that can be refunded","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_total","type":"`number`","description":"The total of gift cards","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"gift_card_tax_total","type":"`number`","description":"The total of gift cards with taxes","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"sales_channels","type":"[SalesChannel](../../entities/classes/entities.SalesChannel.mdx)[]","description":"The associated sales channels.","optional":true,"defaultValue":"","expandable":true,"featureFlag":"medusa_v2","children":[]},{"name":"returnable_items","type":"[LineItem](../../entities/classes/entities.LineItem.mdx)[]","description":"The details of the line items that are returnable as part of the order, swaps, or claims","optional":true,"defaultValue":"","expandable":true,"children":[]}]},{"name":"fulfillment","type":"[Fulfillment](../../entities/classes/entities.Fulfillment.mdx)","description":"The fulfillment being created.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"id","type":"`string`","description":"The fulfillment's ID","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"created_at","type":"`Date`","description":"The date with timezone at which the resource was created.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"updated_at","type":"`Date`","description":"The date with timezone at which the resource was updated.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"claim_order_id","type":"`string`","description":"The ID of the Claim that the Fulfillment belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"claim_order","type":"[ClaimOrder](../../entities/classes/entities.ClaimOrder.mdx)","description":"The details of the claim that the fulfillment may belong to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"swap_id","type":"`string`","description":"The ID of the Swap that the Fulfillment belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"swap","type":"[Swap](../../entities/classes/entities.Swap.mdx)","description":"The details of the swap that the fulfillment may belong to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"order_id","type":"`string`","description":"The ID of the Order that the Fulfillment belongs to.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"order","type":"[Order](../../entities/classes/entities.Order.mdx)","description":"The details of the order that the fulfillment may belong to.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"no_notification","type":"`boolean`","description":"Flag for describing whether or not notifications related to this should be sent.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"provider_id","type":"`string`","description":"The ID of the Fulfillment Provider responsible for handling the fulfillment.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"location_id","type":"`null` \\| `string`","description":"The ID of the stock location the fulfillment will be shipped from","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"provider","type":"[FulfillmentProvider](../../entities/classes/entities.FulfillmentProvider.mdx)","description":"The details of the fulfillment provider responsible for handling the fulfillment.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"items","type":"[FulfillmentItem](../../entities/classes/entities.FulfillmentItem.mdx)[]","description":"The Fulfillment Items in the Fulfillment. These hold information about how many of each Line Item has been fulfilled.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"tracking_links","type":"[TrackingLink](../../entities/classes/entities.TrackingLink.mdx)[]","description":"The Tracking Links that can be used to track the status of the Fulfillment. These will usually be provided by the Fulfillment Provider.","optional":false,"defaultValue":"","expandable":true,"children":[]},{"name":"tracking_numbers","type":"`string`[]","description":"The tracking numbers that can be used to track the status of the fulfillment.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"data","type":"`Record<string, unknown>`","description":"This contains all the data necessary for the Fulfillment provider to handle the fulfillment.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"shipped_at","type":"`Date`","description":"The date with timezone at which the Fulfillment was shipped.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"canceled_at","type":"`Date`","description":"The date with timezone at which the Fulfillment was canceled.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"metadata","type":"`Record<string, unknown>`","description":"An optional key-value map with additional details","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"idempotency_key","type":"`string`","description":"Randomly generated key used to continue the completion of the fulfillment in case of failure.","optional":false,"defaultValue":"","expandable":false,"children":[]}]}]} sectionTitle="createFulfillment"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;[FulfillmentProviderData](../../medusa/types/medusa.FulfillmentProviderData.mdx)&#62;","optional":false,"defaultValue":"","description":"The data that will be stored in the `data` attribute of the created fulfillment.","expandable":false,"children":[{"name":"FulfillmentProviderData","type":"`Record<string, unknown>`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]}]}]} sectionTitle="createFulfillment"/>
### cancelFulfillment
This method is called when a fulfillment is cancelled by the admin. This fulfillment can be for an order, a claim, or a swap.
#### Example
This is the basic implementation of the method for a fulfillment provider that doesn't interact with a third-party provider to cancel the fulfillment:
```ts
class MyFulfillmentService extends FulfillmentService {
// ...
async cancelFulfillment(
fulfillment: Record<string, unknown>
): Promise<any> {
return {}
}
}
```
#### Parameters
<TypeList types={[{"name":"fulfillment","type":"[FulfillmentProviderData](../../medusa/types/medusa.FulfillmentProviderData.mdx)","description":"The `data` attribute of the fulfillment being canceled","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="cancelFulfillment"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;any&#62;","optional":false,"defaultValue":"","description":"The method isn't expected to return any specific data.","expandable":false,"children":[{"name":"any","type":"`any`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="cancelFulfillment"/>
### createReturn
Fulfillment providers can also be used to return products. A shipping option can be used for returns if the `is_return` property is true or if an admin creates a Return Shipping Option from the settings.
This method is used when the admin [creates a return request](https://docs.medusajs.com/api/admin#orders\_postordersorderreturns) for an order,
[creates a swap](https://docs.medusajs.com/api/admin#orders\_postordersorderswaps) for an order, or when the
[customer creates a return of their order](https://docs.medusajs.com/api/store#returns\_postreturns). The fulfillment is created automatically for the order return.
#### Example
This is the basic implementation of the method for a fulfillment provider that does not contact with a third-party provider to fulfill the return:
```ts
class MyFulfillmentService extends AbstractFulfillmentService {
// ...
async createReturn(
returnOrder: CreateReturnType
): Promise<Record<string, unknown>> {
return {}
}
}
```
#### Parameters
<TypeList types={[{"name":"returnOrder","type":"[CreateReturnType](../../medusa/types/medusa.CreateReturnType.mdx)","description":"the return that the fulfillment is being created for.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="createReturn"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;Record&#60;string, unknown&#62;&#62;","optional":false,"defaultValue":"","description":"Used to set the value of the `shipping_data` attribute of the return being created.","expandable":false,"children":[{"name":"Record","type":"`Record<string, unknown>`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="createReturn"/>
### getFulfillmentDocuments
This method is used to retrieve any documents associated with a fulfillment. This method isn't used by default in the backend, but you can use it for custom use cases such as allowing admins to download these documents.
#### Example
```ts
class MyFulfillmentService extends FulfillmentService {
// ...
async getFulfillmentDocuments(
data: Record<string, unknown>
): Promise<any> {
// assuming you contact a client to
// retrieve the document
return this.client.getFulfillmentDocuments()
}
}
```
#### Parameters
<TypeList types={[{"name":"data","type":"[FulfillmentProviderData](../../medusa/types/medusa.FulfillmentProviderData.mdx)","description":"The `data` attribute of the fulfillment that you're retrieving the documents for.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="getFulfillmentDocuments"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;any&#62;","optional":false,"defaultValue":"","description":"There are no restrictions on the returned response. If your fulfillment provider doesn't provide this functionality, you can leave the method empty or through an error.","expandable":false,"children":[{"name":"any","type":"`any`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="getFulfillmentDocuments"/>
### getReturnDocuments
This method is used to retrieve any documents associated with a return. This method isn't used by default in the backend, but you can use it for custom use cases such as allowing admins to download these documents.
#### Example
```ts
class MyFulfillmentService extends FulfillmentService {
// ...
async getReturnDocuments(
data: Record<string, unknown>
): Promise<any> {
// assuming you contact a client to
// retrieve the document
return this.client.getReturnDocuments()
}
}
```
#### Parameters
<TypeList types={[{"name":"data","type":"`Record<string, unknown>`","description":"The data attribute of the return that you're retrieving the documents for.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="getReturnDocuments"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;any&#62;","optional":false,"defaultValue":"","description":"There are no restrictions on the returned response. If your fulfillment provider doesn't provide this functionality, you can leave the method empty or through an error.","expandable":false,"children":[{"name":"any","type":"`any`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="getReturnDocuments"/>
### getShipmentDocuments
This method is used to retrieve any documents associated with a shipment. This method isn't used by default in the backend, but you can use it for custom use cases such as allowing admins to download these documents.
#### Example
```ts
class MyFulfillmentService extends FulfillmentService {
// ...
async getShipmentDocuments(
data: Record<string, unknown>
): Promise<any> {
// assuming you contact a client to
// retrieve the document
return this.client.getShipmentDocuments()
}
}
```
#### Parameters
<TypeList types={[{"name":"data","type":"`Record<string, unknown>`","description":"The `data` attribute of the shipment that you're retrieving the documents for.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="getShipmentDocuments"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;any&#62;","optional":false,"defaultValue":"","description":"There are no restrictions on the returned response. If your fulfillment provider doesn't provide this functionality, you can leave the method empty or through an error.","expandable":false,"children":[{"name":"any","type":"`any`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="getShipmentDocuments"/>
### retrieveDocuments
This method is used to retrieve any documents associated with an order and its fulfillments. This method isn't used by default in the backend, but you can use it for
custom use cases such as allowing admins to download these documents.
#### Example
```ts
class MyFulfillmentService extends FulfillmentService {
// ...
async retrieveDocuments(
fulfillmentData: Record<string, unknown>,
documentType: "invoice" | "label"
): Promise<any> {
// assuming you contact a client to
// retrieve the document
return this.client.getDocuments()
}
}
```
#### Parameters
<TypeList types={[{"name":"fulfillmentData","type":"`Record<string, unknown>`","description":"The `data` attribute of the order's fulfillment.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"documentType","type":"`\"label\"` \\| `\"invoice\"`","description":"The type of document to retrieve.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} sectionTitle="retrieveDocuments"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;any&#62;","optional":false,"defaultValue":"","description":"There are no restrictions on the returned response. If your fulfillment provider doesn't provide this functionality, you can leave the method empty or through an error.","expandable":false,"children":[{"name":"any","type":"`any`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} sectionTitle="retrieveDocuments"/>
---
## Test Implementation
:::note
If you created your fulfillment provider in a plugin, refer to [this guide on how to test plugins](https://docs.medusajs.com/development/plugins/create#test-your-plugin).
:::
After finishing your fulfillment provider implementation:
1\. Run the `build` command in the root of your Medusa backend:
```bash npm2yarn
npm run build
```
2\. Start the backend with the `develop` command:
```bash
npx medusa develop
```
3\. Enable your fulfillment provider in one or more regions. You can do that either using the [Admin APIs](https://docs.medusajs.com/api/admin#regions_postregionsregionfulfillmentproviders) or the [Medusa Admin](https://docs.medusajs.com/user-guide/regions/providers#manage-fulfillment-providers).
4\. To test out your fulfillment provider implementation, create a cart and complete an order. You can do that either using the [Next.js starter](https://docs.medusajs.com/starters/nextjs-medusa-starter) or [using Medusa's APIs and clients](https://docs.medusajs.com/modules/carts-and-checkout/storefront/implement-cart).