Workflow

eBay Fulfillment API Pagination: 200-Order Limit and Offset Gotchas

When automating order fetching from eBay via the Fulfillment API, you'll quickly encounter the 200-order limit per request. Unlike some APIs that use cursor-based pagination, eBay's Fulfillment API relies on a limit and offset approach. While straightforward, this method has specific gotchas that can lead to missed orders or duplicated data if not handled correctly, especially in a dynamic dropshipping environment where order statuses change frequently.

Advertisement

Understanding the limit and offset Parameters

The eBay Fulfillment API's GET /order endpoint accepts two primary pagination parameters:

  • limit: Specifies the maximum number of orders to return in a single response. The maximum allowed value is 200.
  • offset: Specifies the number of orders to skip from the beginning of the result set. This is how you move through pages of results. An offset of 0 returns the first page, an offset of 200 returns the second page (assuming a limit of 200), and so on.

For example, to fetch orders 201-400, your request would include ?limit=200&offset=200.

The Total Number of Orders: total Field

Each successful response from the GET /order endpoint includes a total field at the root level. This field indicates the total number of orders that match your query criteria (e.g., creationDateRange). This is crucial for determining how many requests you need to make to fetch all relevant orders.

Always use the total field from the API response to calculate the number of subsequent requests. Do not hardcode an arbitrary number of pages.

The Dynamic Data Problem: Why Simple Offset Fails

The most common pitfall with limit/offset pagination, particularly with data that changes frequently (like order statuses), is that the underlying dataset can shift between requests. Imagine this scenario:

  1. You make an initial request: GET /order?limit=200&offset=0&creationDateRange=.... The response indicates total: 405 orders. You retrieve orders 1-200.
  2. You calculate that you need to make two more requests: offset=200 and offset=400.
  3. Before your next request for offset=200, five new orders are placed that match your creationDateRange. The total number of orders for your query is now 410.
  4. You make your second request: GET /order?limit=200&offset=200&creationDateRange=.... You retrieve orders 206-405 (because the first 200 orders shifted, and 5 new orders pushed everything down).
  5. You make your third request: GET /order?limit=200&offset=400&creationDateRange=.... You retrieve orders 406-410.

In this scenario, orders 201-205 were completely missed because they were part of the 'first page' when you requested the second, and then 'shifted out' of the second page when you requested the third. Conversely, if orders are cancelled or fulfilled and removed from the queried set between requests, you could end up fetching the same orders multiple times.

Advertisement

Robust Pagination Strategy for eBay Fulfillment API

To reliably fetch all orders without omissions or excessive duplication, implement the following strategy:

1. Define a Consistent Query

Ensure your query parameters (especially creationDateRange or lastModifiedDateRange) remain identical across all paginated requests for a single batch. If you're fetching all orders from the last 24 hours, that time window must be static for all limit/offset calls within that batch.

2. Iterate Until No More Orders

Instead of pre-calculating the number of pages based on the initial total, iterate until the API returns fewer orders than your specified limit, or until the offset exceeds the total.

current_offset = 0
all_orders = []

while True:
    response = make_api_request(limit=200, offset=current_offset, ...)
    orders_batch = response.get('orders', [])
    total_orders_in_query = response.get('total', 0)

    if not orders_batch:
        # No more orders to fetch for this query
        break

    all_orders.extend(orders_batch)
    current_offset += len(orders_batch)

    # Break if we've fetched all available orders based on the total
    # or if the last batch was smaller than the limit (implying it's the last page)
    if len(orders_batch) < 200 or current_offset >= total_orders_in_query:
        break

    # Optional: Add a small delay between requests to avoid rate limits
    # time.sleep(0.1)

3. Deduplicate on Your End

Even with the robust iteration above, it's good practice to deduplicate orders by orderId on your end. This is especially true if you're fetching orders frequently (e.g., every 5 minutes) and there's an overlap in your creationDateRange or lastModifiedDateRange. Store fetched orderIds in a set and only process new ones.

4. Prioritize lastModifiedDateRange for Updates

For identifying order updates (e.g., a refund initiated, logistics_status changing), use the lastModifiedDateRange parameter instead of creationDateRange. This allows you to specifically query for orders that have changed since your last sync, minimizing the dataset you need to paginate through.

Example Workflow for Fetching New and Updated Orders

Let's say you want to fetch all new orders from the last 24 hours and all orders modified in the last 6 hours.

  1. Fetch New Orders (creationDateRange):
    Set creationDateRange for the last 24 hours. Iterate with limit=200 and increasing offset until orders_batch is empty or len(orders_batch) < 200. Add all unique orderIds to a set of processed orders and store the full order details.
  2. Fetch Updated Orders (lastModifiedDateRange):
    Set lastModifiedDateRange for the last 6 hours. Iterate with limit=200 and increasing offset. For each order fetched:
    • Check if its orderId is already in your set of processed orders.
    • If it is, update the existing order's details in your system.
    • If it's not (meaning it was created more than 24 hours ago but modified recently), add it as a new record or update as needed.

This two-pronged approach ensures you capture both newly created orders and significant updates to older orders, which is critical for timely refund detection (e.g., gmt_refund timestamp) or tracking logistics changes (e.g., logistics_status updates like SHIPPED or DELIVERED).

By understanding the nuances of eBay's limit/offset pagination and implementing a robust iteration and deduplication strategy, you can ensure your Fetch Order Tracking system reliably captures all necessary order data for your eBay × AliExpress dropshipping operation. For more insights on streamlining your dropshipping workflow, visit our homepage.

Advertisement

Try the fetcher More guides