Managing a fulfillment order

In Digital River coordinated fulfillments, learn how to use the Fulfillment Orders API and Shipments API to manage fulfillment of physical products

A fulfillment order manages the fulfillment of a transaction's SKU-inventory item pairs. You only use this resource in Digital River coordinated fulfillments.

If you're using the distributed model, you must send a create fulfillment order request to initiate physical fulfillment.

If you're using the orchestrated model, Digital River submits this fulfillment order request for you.

In both the distributed and orchestrated models, you should subscribe to events that occur during a fulfillment order's lifecycle. These events notify you of (1) pending shipments, (2) backordered products, (3) shipped products and (4) product cancellations.

You can also use shipments to track the progress of a delivery.

Creating a fulfillment order

In the distributed model, once you either synchronously or asynchronously receive an order in an accepted state, your integration should handle the order state change event by sending a create fulfillment order request. This POST/fulfillment-orders request initiates the fulfillment of a transaction's SKU-inventory item pairs.

In the orchestrated model, we listen for an accepted order and handle this state change event by internally submitting a create fulfillment order request.

The following describes the request's required data and optional data:

For a full list of specifications, refer to the Fulfillment Orders APIs reference documentation.

Required data

Every POST/fulfillment-orders request must include currency, created time, shipping address, shipping method, and product data.

This required data can be retrieved from an order in an accepted state:

Order in an accepted state

POST/fulfillment-orders

currency

currency

createdTime

upstreamOrderTime

shipTo.country

shipTo.country

shippingChoice.serviceLevel

shippingChoice.id

items[].skuId

items[].inventoryItemId

items[].quantity

items[].quantity

items[].tax.amount

items[].tax.amount

Optional data

In addition to other optional data, a POST/fulfillment-orders request accepts product, customer, ship to, upstream order identifier, and locale data. If you placed a hold on products, you should also attach the reservation identifier.

This optional data can be retrieved from an order in an accepted state:

items[].id

items[].upstreamId

items[].amount

items[].total

shipTo.nameor billTo.name

name or shipTo.name

shipTo.phoneor billTo.phone

phone or shipTo.phone

shipTo.emailor billTo.email

email or shipTo.email

shipTo

shipTo

id

upstreamId

locale

locale

checkoutId

reservationId

Currency

The currency in the request should be the same as the value in the upstream order. This avoids creating downstream invoicing errors, issues with customs, and incorrect tax computations.

Upstream order time

As with all dates and times in the Digital River APIs, the createdTime of the upstream order is in UTC and adheres to the ISO-8601 standard. You should not modify this date-time value before using it to set upstreamOrderTime in a fulfillment order.

{
    "id": "186962110336",
    "createdTime": "2021-04-02T18:46:45Z",
    ...
}

Customer information

You can set the customer's name, email, and phone at the fulfillment order level and within shipTo.

Ship to address

The fulfillment order's shipTo values should be the same as the upstream order's shipTo.

Attaching a reservation

The fulfillment order's reservationId should reference the reservation that was used to place a hold on the products.

If the create fulfillment order request doesn't contain a reservationId, Digital River still attempts to allocate the specified inventory items. If we determine inventory levels are too low, what happens at that point depends on whether you allow overselling of an item and whether your channel is set up to accept backorders.

Shipping choices

When setting the fulfillment order's shippingChoice.id, you should use the order's shippingChoice.serviceLevel . This value maps to the identifier of the shipping quote selected by the customer.

Shipping quoteOrderFulfillment Order

id

shippingChoice.serviceLevel

shippingChoice.id

If you want to set the fulfillment order's signatureRequiredType, you'll need to persist the shipping quote selected by the customer. You can then retrieve the shipping quote's signatureRequiredType and use that value to set the fulfillment order's signatureRequiredType.

If the upstream order triggers the landed cost feature, then set the fulfillment order's dutiesPaid to true. This notifies the shipping carrier that the customer has already paid the full landed cost and they should invoice you for any duties paid.

Product information

Use the fulfillment order's items array to specify product information. The line items must be retrieved from the upstream order. The same is true for most of a fulfillment order's optional product data.

For example, you can use giftMessage to send the downstream fulfiller a message that customers want included with the package. The giftWrap flag allows you to indicate whether the product should be wrapped.

A fulfillment order

Once you successfully submit a POST/fulfillment-orders request, a fulfillment order contains unique identifiers that are needed for downstream processing. Additionally, we return attributes that inform you of a fulfillment order's state and categorize the status of its line items.

Unique identifiers

Once a fulfillment order is created, we assign it a unique identifier. We also assign unique identifiers to each of its line items. You should persist all of these values.

You'll need the fulfillment order identifier to retrieve the object.

When submitting product cancellation requests and product return requests, you must provide both the fulfillment order identifier and the relevant line item identifiers.

In the distributed model, you can retrieve these identifiers from the 201 Created response to a POST/fulfillment-orders request.

In the orchestrated model, you can retrieve these identifiers by listening for the fulfillment_order.pending event.

The fulfillment order life cycle

You should be aware of both the fulfillment order's lifecycle and the fulfillment order's line item's lifecycle. In both, each stage of the lifecycle is represented by a state.

Fulfillment order level

The state attribute at the fulfillment order level indicates where a fulfillment order is in its lifecycle. The values for successful fulfillment (i.e., the happy path) are pending > shipped.

(1) When the fulfillment order...

(2) its state transitions to...

is created but not yet partially or fully shipped

pending

partially or fully ships

shipped

is cancelled by the customer, the client or the fulfiller

cancelled

Line item level

The line item state attribute indicates where a fulfillment order's line item is in its lifecycle. The values for a successfully fulfilled line item (i.e., the happy path) are pending > shipped.

(1) When the line item...

(2) its state transitions to...

has not yet partially or fully shipped

pending

is configured to allow oversell and is awaiting restocking

backordered

partially or fully ships

shipped

is cancelled by the customer, the client or the fulfiller

cancelled

Product status by category

Each element of fulfillment order's items array indicates how many items are pending, backordered, shipped, cancelled, and returned. In aggregate, these values equal the total quantity of that line item, which represents the amount originally purchased by the customer.

Monitoring and responding to a fulfillment order

You can determine a fulfillment order's state by either calling the API or listening for webhook events.

Retrieving a fulfillment order

There are two methods in the Fulfillment Orders API that can be used to retrieve fulfillment orders. You can either get a list of fulfillment orders filtered by optional query parameters. Or you can get an individual fulfillment order by including its unique identifier as a path parameter in the request.

Listening and responding to fulfillment order events

We recommend you respond to a fulfillment order's state changes by listening for the pending, backordered, shipped, and cancelled events.

In all of these events, data.object contains the unique identifier of:

Fulfillment order pending events

When Digital River queues a fulfillment order for creation, we create a fulfillment_order.pending event. The event's data.object is a fulfillment order in a pending state.

In the orchestrated model, use this event to retrieve and save the fulfillment order's identifier as well as each of its line item's identifiers.

A pending fulfillment order doesn't necessarily mean that all of its line items are also pending. A line item can be pending, shipped, backordered or cancelled while the fulfillment order is still pending.

Fulfillment order backordered events

Upon receiving a backordered notification from your channel's designated fulfiller, Digital River sends you a fulfillment_order.backordered event. The event's data.object contains an array of backordered items.

For each product in the items array, we provide an estimated availableTime (assuming the fulfiller sends us this information). We also specify the original ordered quantity as well as the quantity of backOrdered items that triggered the event.

The totalBackordered is the aggregated backOrdered quantity from all the backordered events. When processing duplicate backordered events, you can use this value as a checksum, thereby ensuring your system does not exceed the total ordered amount.

You can use the fulfillment_order.backordered event as a trigger to send a delayed order notification (typically an email) to the customer. In the email, we recommend providing a link directing customers to their order management page.

On this page, you should allow customers to cancel the order fully or partially. If they select either option, make sure you respond to this event by submitting a create fulfillment cancellation request.

{
    "id": "evt_e381g2ff-7d42-3b05-91d5-e711443r3521",
    ...
    "data": {
        "object": {
            ...
            "items": [
                {
                    ...
                    "ordered": 6,
                    "backordered": 2,
                    "totalBackordered": 3,
                    "availableTime": 2020-11-25T20:36:00Z,
                    ...
                }
            ],
            ...
        },
        "previousAttributes": {}
    },
    ...
    "type": "fulfillment_order.backordered"
}

Fulfillment order shipped events

Once Digital River receives a shipped notification from your channel's designated fulfiller, we create an event with a type of fulfillment_order.shipped. Its data.object consists of a shipment. To track a shipment's progress, persist data.object.id, which represents the shipment's identifier.

In the event's payload, fulfillmentOrderUpstreamId represents the order's id and each items[].fulfillmentOrderItemUpstreamId maps to an items[].id in that order.

{
    "id": "evt_d290f1ee-6c54-4b01-90e6-d701748f0851",
    ...
    "data": {
        "object": {
            "id": "29016544906",
            ...
            "fulfillmentOrderId": "5774321009",
            "fulfillmentOrderUpstreamId": "9292981838",
            ...
            "items": [
                {
                    "id": "8760948870",
                    "fulfillmentOrderItemId": "650398674428",
                    "fulfillmentOrderItemUpstreamId": "650398674428",
                    ...
                    "quantity": 1,
                    ...
                }
            ],
            ...
        },
        "previousAttributes": {}
    },
    ...
    "type": "fulfillment_order.shipped"
}

In the distributed model, respond to this event by sending a POST /fulfillments, which captures the appropriate amount of an order's payment charges.

The following table lists the data to retrieve from the event and then pass in a POST /fulfillments.

Event

POST /fulfillments

data.object.id

shipmentId

items[].id

items[].shipmentItemId

fulfillmentOrderUpstreamId

orderId

items[].fulfillmentOrderItemUpstreamId

items[].itemId

items[].quantity

items[].quantity

Fulfillment order cancelled events

Whenever a fulfillment order is fully or partially cancelled, we send you a fulfillment_order.cancelled event.

The source of these events are either POST/fulfillment-cancellations requests that your system submits or cancellation notifications sent by the product's fulfiller. The event's data.object is a fulfillment order in a cancelled state.

In the event's payload, upstreamId represents the order's unique identifier and items[].upstreamId represents a line item's identifier in an order.

In the distributed model, every time you receive fulfillment_order.cancelled, retrieve data from the event and send it in a POST/fulfillments request. This request instructs Digital River to cancel the appropriate amount of an order's payment charges.

In the orchestrated model, we listen for the cancelled event and respond to it by submitting an internal payment cancel request.

The following table lists the data you must retrieve from each fulfillment_order.cancelled event and then pass in a POST/fulfillments.

fulfillment_order.cancelled event

POST/fulfillments

upstreamId

orderId

items[].upstreamId

items[].itemId

items[].cancelled

items[].cancelQuantity

Tracking a shipment

The products in a fulfillment order can be delivered to the end customer in one or more shipments. Each of these shipments is represented by the Shipment resource.

You can use the unique shipment identifier you receive in a fulfillment_order.shipped event to submit queries that return a shipment's contents and provide tracking information.

Querying the Shipments API

There are two methods for querying the Shipments API. You can either retrieve an individual shipment by sending its unique identifier as a path parameter in a GET/shipments/{id} request. Or you can submit a GET/shipments request to retrieve a list of shipments and use optional query parameters to filter the results.

Determining the contents of a shipment

A shipment's items array returns each shipment item's unique identifier and the item's shipped quantity. All the relevant upstream identifiers of the item are also included.

Additionally, when the shipped item is a smartphone or cellphone, the downstream fulfiller may pass back to you unitAttributes that help identify and track the device. These attributes consist of a serial, IMEI, or SIM card number

Monitoring the progress of a shipment

A shipment provides numerous data points that you can use to track a delivery's progress.

For the entire shipment, we provide you a trackingUrl that directs customers to a page where they can enter the trackingNumber provided by the trackingCompany.

At the shipment item level, we also give you a trackingUrl that directs customers to a page where they can enter the item's trackingNumber and monitor the delivery progress of specific products.

Last updated