Complete Integration Guide
This guide walks you through integrating with the Fulfillbot API, from creating your first API Key to placing a complete purchase order and shipping internationally. Follow these steps in order to build a complete cross-border purchasing workflow.
Create an API Key
Go to your API Keys management page and create a new key. Choose the scopes you need for your integration:
Recommended scopes by use case:
products:readproducts:read, cart:read, cart:write, orders:read, orders:write, wallet:readwarehouse:read, shipping:read, shipping:write, logistics:readAll scopessk- prefix. # Store your key securely (e.g. environment variable) export FULFILLBOT_API_KEY="sk-a1b2c3d4e5f6..." # Test your key curl -s https://api.fulfillbot.com/api/v1/open/user/profile \ -H "Authorization: Bearer $FULFILLBOT_API_KEY" | json_pp
Search Products
Search across multiple Chinese e-commerce platforms. You can search the local catalog or directly query Taobao, 1688, and Weidian.
Search local catalog
curl "https://api.fulfillbot.com/api/v1/open/products/search?q=sneakers&page=1&limit=20" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
Search on Taobao directly
curl "https://api.fulfillbot.com/api/v1/open/products/platform/taobao/search?q=sneakers&page=1" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
Get product details
# Get detailed info including SKU variants, prices, images curl "https://api.fulfillbot.com/api/v1/open/products/12345" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
Response structure
{
"data": {
"items": [
{
"id": 12345,
"title": "Nike Air Max 90",
"price": 299.00,
"currency": "CNY",
"platform": "taobao",
"imageUrl": "https://...",
"shopName": "Nike Official Store",
"skus": [
{ "skuId": "s001", "name": "Black / US 9", "price": 299.00, "stock": 50 }
]
}
],
"total": 156,
"page": 1,
"limit": 20
}
}Add to Cart
Add products to your shopping cart. You can add items one at a time or in batch.
Add single item
curl -X POST "https://api.fulfillbot.com/api/v1/open/cart/items" \
-H "Authorization: Bearer $FULFILLBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"productId": "12345",
"skuId": "s001",
"quantity": 2,
"remark": "Size US 9, black color"
}'Batch add items
curl -X POST "https://api.fulfillbot.com/api/v1/open/cart/items/batch" \
-H "Authorization: Bearer $FULFILLBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "productId": "12345", "skuId": "s001", "quantity": 2 },
{ "productId": "67890", "skuId": "s010", "quantity": 1 }
]
}'View cart
curl "https://api.fulfillbot.com/api/v1/open/cart" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
Place Purchase Order
Create a purchase order. Our team will purchase the items from the Chinese platform on your behalf. The product cost will be deducted from your wallet balance.
curl -X POST "https://api.fulfillbot.com/api/v1/open/orders" \
-H "Authorization: Bearer $FULFILLBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"productId": "12345",
"skuId": "s001",
"quantity": 2,
"remark": "Please check quality carefully"
}
],
"remark": "Handle with care"
}'Order lifecycle:
Poll order status
# Check order status
curl "https://api.fulfillbot.com/api/v1/open/orders/ORD-20240101-001/status" \
-H "Authorization: Bearer $FULFILLBOT_API_KEY"
# Response:
# { "data": { "status": "purchased", "updatedAt": "2024-01-02T10:00:00Z" } }Check Warehouse Inventory
After purchase and quality inspection, items arrive at our warehouse. Query your inventory to see what's ready to ship.
# Get all warehouse packages curl "https://api.fulfillbot.com/api/v1/open/warehouse/packages?page=1&limit=20" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY" # Get shippable packages only curl "https://api.fulfillbot.com/api/v1/open/warehouse/packages/shippable" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY" # Get warehouse statistics curl "https://api.fulfillbot.com/api/v1/open/warehouse/packages/stats" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
Package stats response
{
"data": {
"total": 5,
"inWarehouse": 3,
"shipped": 2,
"totalWeight": 2450
}
}Calculate Shipping
Before creating a shipping order, calculate the freight cost by querying available channels and their prices.
1. Get supported countries
curl "https://api.fulfillbot.com/api/v1/open/logistics/countries" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
2. Get available shipping methods
curl "https://api.fulfillbot.com/api/v1/open/logistics/shipping-methods?country=US&weight=1500" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
3. Calculate freight for all channels
curl -X POST "https://api.fulfillbot.com/api/v1/open/logistics/calculate-freight-batch" \
-H "Authorization: Bearer $FULFILLBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"country": "US",
"weight": 1500,
"length": 30,
"width": 20,
"height": 15
}'
# Response: list of channels with prices, delivery times, etc.Create Shipping Order
Select packages from your warehouse, choose a shipping channel, provide the delivery address, and create the shipping order.
curl -X POST "https://api.fulfillbot.com/api/v1/open/shipping/create" \
-H "Authorization: Bearer $FULFILLBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "inventoryId": 101, "quantity": 1 },
{ "inventoryId": 102, "quantity": 1 }
],
"logisticsChannelId": "ch-001",
"recipientName": "John Doe",
"recipientPhone": "+1-555-0123",
"recipientCountry": "US",
"recipientState": "California",
"recipientCity": "Los Angeles",
"recipientAddress": "123 Main St, Apt 4B",
"recipientZipCode": "90001",
"remark": "Please use reinforced packaging"
}'Track shipping status
# Get shipping order detail curl "https://api.fulfillbot.com/api/v1/open/shipping/orders/SHP-001" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY" # Confirm delivery after receiving curl -X POST "https://api.fulfillbot.com/api/v1/open/shipping/orders/SHP-001/confirm-delivery" \ -H "Authorization: Bearer $FULFILLBOT_API_KEY"
Complete Flow Diagram
Dashboard → API KeysGET /products/searchPOST /cart/itemsPOST /ordersGET /orders/:id/inspectionGET /warehouse/packages/shippablePOST /logistics/calculate-freight-batchPOST /shipping/createPOST /shipping/orders/:id/confirm-deliveryFull Python Example
import requests
import time
API_KEY = "sk-your-api-key"
BASE = "https://api.fulfillbot.com/api/v1/open"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
def search_products(keyword, page=1):
"""Search products on Taobao"""
resp = requests.get(f"{BASE}/products/platform/taobao/search",
params={"q": keyword, "page": page}, headers=HEADERS)
resp.raise_for_status()
return resp.json()["data"]
def add_to_cart(product_id, sku_id, quantity=1):
"""Add product to cart"""
resp = requests.post(f"{BASE}/cart/items", headers=HEADERS,
json={"productId": product_id, "skuId": sku_id, "quantity": quantity})
resp.raise_for_status()
return resp.json()["data"]
def create_order(items, remark=""):
"""Create purchase order"""
resp = requests.post(f"{BASE}/orders", headers=HEADERS,
json={"items": items, "remark": remark})
resp.raise_for_status()
return resp.json()["data"]
def wait_for_warehouse(order_id, timeout=86400, interval=300):
"""Poll until order arrives at warehouse"""
start = time.time()
while time.time() - start < timeout:
resp = requests.get(f"{BASE}/orders/{order_id}/status", headers=HEADERS)
status = resp.json()["data"]["status"]
print(f"Order {order_id}: {status}")
if status in ("in_warehouse", "completed"):
return True
if status in ("cancelled", "refunded"):
return False
time.sleep(interval)
return False
def get_shippable_packages():
"""Get packages ready to ship"""
resp = requests.get(f"{BASE}/warehouse/packages/shippable", headers=HEADERS)
resp.raise_for_status()
return resp.json()["data"]
def calculate_shipping(country, weight):
"""Calculate all shipping options"""
resp = requests.post(f"{BASE}/logistics/calculate-freight-batch",
headers=HEADERS, json={"country": country, "weight": weight})
resp.raise_for_status()
return resp.json()["data"]
def create_shipping_order(items, channel_id, address):
"""Create shipping order"""
resp = requests.post(f"{BASE}/shipping/create", headers=HEADERS,
json={"items": items, "logisticsChannelId": channel_id, **address})
resp.raise_for_status()
return resp.json()["data"]
# ---- Main Flow ----
if __name__ == "__main__":
# 1. Search
results = search_products("Nike Air Max")
product = results["items"][0]
print(f"Found: {product['title']} - {product['price']} CNY")
# 2. Create order directly
order = create_order([{
"productId": product["id"],
"skuId": product["skus"][0]["skuId"],
"quantity": 1
}])
print(f"Order created: {order['orderNo']}")
# 3. Wait for warehouse arrival
if wait_for_warehouse(order["orderNo"]):
# 4. Get shippable packages
packages = get_shippable_packages()
# 5. Calculate shipping
total_weight = sum(p["weight"] for p in packages["items"])
options = calculate_shipping("US", total_weight)
cheapest = min(options["channels"], key=lambda c: c["totalPrice"])
print(f"Cheapest shipping: {cheapest['name']} - {cheapest['totalPrice']} CNY")
# 6. Create shipping order
ship = create_shipping_order(
items=[{"inventoryId": p["id"], "quantity": 1} for p in packages["items"]],
channel_id=cheapest["channelId"],
address={
"recipientName": "John Doe",
"recipientPhone": "+1-555-0123",
"recipientCountry": "US",
"recipientCity": "Los Angeles",
"recipientAddress": "123 Main St",
"recipientZipCode": "90001"
}
)
print(f"Shipping order created: {ship['orderNo']}")Best Practices
Do
- Store your API Key in environment variables, never in code
- Use minimal scopes - only request permissions you actually need
- Implement retry logic with exponential backoff for rate limits
- Check wallet balance before placing orders
- Use IP whitelisting in production for security
- Poll order status at reasonable intervals (every 5-10 minutes)
- Handle all error responses gracefully
Don't
- Hardcode API Keys in source code or commit to Git
- Share API Keys between different applications
- Ignore rate limit headers - implement proper throttling
- Poll status too frequently (no more than once per minute)
- Create orders without checking product availability first
- Skip error handling - API calls can fail for various reasons
- Use excessive scopes that your integration doesn't need
message field. The API returns descriptive error messages that can help with debugging.