- Start here
- Getting Started
- Development Store
- Build an app
-
App Development
-
Webhooks
- Guides by use case
- Popular APIs
-
Logistic Apps
- Reference
- Authentication
- API access scopes
- API call limit
- Response status codes
- API 3.0 reference ↗
- API 4.0 reference ↗
- EasyStore App Store ↗
Order Fulfillment
Order fulfillment integration allows merchants to create shipments and push order details to your logistics platform directly from the EasyStore admin panel.
How It Works
- Merchant selects orders to fulfill from EasyStore admin panel
- Merchant clicks "Fulfill" button and selects your app
- EasyStore sends a request to your registered fulfillment URL with order details
- Your app returns a response to display your fulfillment UI (iframe) or show an error message
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ Order Fulfillment Flow │
└─────────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Merchant │ │ EasyStore │ │ Your App │ │ Logistics │ │ EasyStore │
│ Admin Panel │ │ Server │ │ (iframe) │ │ API │ │ Fulfill API │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │ │ │
│ 1. Click "Fulfill"│ │ │ │
│ Select App │ │ │ │
│ ─────────────────►│ │ │ │
│ │ │ │ │
│ │ 2. POST Request │ │ │
│ │ ─────────────────►│ │ │
│ │ • order details │ │ │
│ │ • shop info │ │ │
│ │ │ │ │
│ │ 3. Return iframe │ │ │
│ │ ◄─────────────────│ │ │
│ │ HTML/URL │ │ │
│ │ │ │ │
│ 4. Display iframe │ │ │ │
│ ◄─────────────────│ │ │ │
│ (Your App UI) │ │ │ │
│ │ │ │ │
│ 5. Confirm Ship │ │ │ │
│ ══════════════════════════════════════► │ │
│ │ │ │ │
│ │ │ 6. Create Shipment│ │
│ │ │ ─────────────────►│ │
│ │ │ • sender address │ │
│ │ │ • receiver address│ │
│ │ │ • parcel details │ │
│ │ │ │ │
│ │ │ 7. Tracking Info │ │
│ │ │ ◄─────────────────│ │
│ │ │ • tracking_number │ │
│ │ │ • tracking_url │ │
│ │ │ │ │
│ │ │ 8. Create Fulfillment │
│ │ │ ─────────────────────────────────────►│
│ │ │ POST /orders/:id/fulfillments.json │
│ │ │ • tracking_number │ │
│ │ │ • courier │ │
│ │ │ │ │
│ │ │ 9. Fulfillment Created │
│ │ │ ◄─────────────────────────────────────│
│ │ │ │ │
│ 10. Success │ │ │ │
│ ◄══════════════════════════════════════ │ │
│ Show success page │ │
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
Handler Responsibilities
When your fulfillment URL receives a request from EasyStore, your handler is responsible for:
1. Create shipping record in your logistics platform
- Send the order details to your logistics/courier API
- Request a shipping delivery for the fulfillment
- Obtain tracking number and other shipment information
2. Create fulfillment record in EasyStore
- Call the EasyStore Create Fulfillment API to mark the order as fulfilled
- This syncs the fulfillment status back to the merchant's admin panel
Registering Your Fulfillment URL
To register your fulfillment endpoints, please email dev@easystore.co with the following information:
- Your app name
- Fulfillment URL endpoints for the topics you want to support:
fulfillment/single- Single order fulfillmentfulfillment/bulk- Bulk order fulfillment
EasyStore team will manually configure the endpoints for your app.
Request Headers
EasyStore includes the following headers with each fulfillment request:
| Header | Value |
|---|---|
Easystore-Topic |
fulfillment/single or fulfillment/bulk |
Easystore-Shop-Domain |
Store's EasyStore domain (e.g., myshop.easy.co) |
Easystore-Hmac-Sha256 |
HMAC-SHA256 signature of payload using app secret |
Content-Type |
application/json |
User-Agent |
EasyStore |
Request Format
Single Fulfillment (fulfillment/single)
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
int | Yes | Single order ID |
fulfillment_order_id |
int | Optional | Fulfillment order ID |
{
"id": 12345,
"fulfillment_order_id": 11111
}
Bulk Fulfillment (fulfillment/bulk)
| Parameter | Type | Required | Description |
|---|---|---|---|
ids |
array | Yes | Array of order IDs |
{
"ids": [12345, 12346, 12347]
}
Response Format
Your endpoint should return a JSON response with the following structure:
| Field | Type | Description |
|---|---|---|
type |
string | Either "link" (success) or "message" (error/info) |
url |
string | The redirect URL (only when type is "link") |
message |
string | Error/info message (only when type is "message") |
style |
string | Message style, e.g., "error" (only when type is "message") |
Link Response (type: "link")
Both single and bulk fulfillment can return a link type response. EasyStore will open the provided URL
as an iframe within the Admin Panel. This allows your integration to render custom UI for the
fulfillment process.
{
"type": "link",
"url": "https://apps.easystore.co/logistics/{app_handle}/fulfillment?shop={shop}&order_id={id}"
}
Message Response (type: "message")
The message type is used to display a toast notification in the Admin Panel. This is
useful for showing error messages or other information to the merchant.
{
"type": "message",
"message": "No shipping app found",
"style": "error"
}
Create Fulfillment API
After successfully creating a shipment in your logistics platform, use this API to create a fulfillment record in EasyStore:
curl --location 'https://{shop}/api/3.0/orders/:order_id/fulfillments.json' \
--header 'EasyStore-Access-Token: {app_access_token}' \
--header 'Content-Type: application/json' \
--data '{
"tracking_company": "AllSome Fulfillments",
"tracking_number": "EN813659438MY",
"tracking_url": "https://tracking_url.com/EN813659438MY",
"status": "in_transit",
"service": "AllSome Fulfillment Malaysia",
"message": "Your fulfillment is complete",
"is_mail": 1,
"app_handle": "sample-app",
"line_items": [
{
"id": 4445896,
"quantity": 1
}
],
"fulfillment_order": {
"fulfillment_order_id": 11111,
"line_items": [
{
"id": 4445896,
"quantity": 1,
"name": "Sample Product",
"fulfillment_order_item_id": 98765
}
]
}
}'
| Parameter | Type | Description |
|---|---|---|
tracking_company |
string | Name of the courier/logistics provider (called courier when you update a fulfillment) |
tracking_number |
string | Parcel tracking number |
tracking_url |
string | URL for tracking the parcel |
status |
string | Initial status of the fulfillment (e.g., in_transit) |
service |
string | Name of the shipping service |
message |
string | Message to display to the merchant |
is_mail |
int | Set to 1 to send shipping notification email to customer |
app_handle |
string | Your app's handle identifier |
line_items |
array | Original array of line items being fulfilled with their id and quantity |
fulfillment_order |
object | Fulfillment order payload containing fulfillment_order_id and line_items |
fulfillment_order.fulfillment_order_id |
int | Fulfillment order ID for this shipment |
fulfillment_order.line_items |
array | Array of line items with id, quantity, name, and fulfillment_order_item_id |
📖 Full documentation on Create Fulfillment API: EasyStore Postman Collection
Which rate did the customer choose?
To ship with the service the customer picked at checkout, read the order with GET /api/3.0/orders/:order_id.json (scope read_orders). The order's
shipping_fees list has the selected shipping method:
nameandprice: the method name and fee shown to the customerstore_app_id: for rates from your app, a handle in the form{store_app_id}-shipping-{rate_id}, whererate_idis theidyou returned in the shipping rate response
Give each rate a stable id that identifies your service (for example express or
standard), so you can map it back when fulfilling the order.
Next Steps
After implementing fulfillment, learn how to enable AWB Printing so merchants can print shipping labels.