Skip to content

Order History

API Type

eCommerce API - Uses API key in request body. See Authentication.

Retrieve order history for a user with pagination support.

Get Order History

Fetch a user's past orders with detailed information about products, pricing, and status.

Endpoint

POST https://{ecomm}.photobook.ai/api/v2/user/get-order-history.php

Replace {ecomm} with your assigned client identifier.

Example: https://yourclient.photobook.ai/api/v2/user/get-order-history.php

Authentication

See Authentication - eCommerce

Request Parameters

json
{
  "env": "dev",
  "key": "your-api-key",
  "marketId": 0,
  "language": "en",
  "email": "user@example.com",
  "cursor": "optional-pagination-token"
}
ParameterTypeRequiredDescription
envstringYesTarget environment: dev or prod
keystringYesYour programmatic access key
marketIdintegerNoTarget market ID. Defaults to 0
languagestringNoFirst 2 characters of language code (e.g., en). Defaults to en
emailstringYesUser's email address (plaintext, not encrypted)
cursorstringNoPagination token from previous response. Fetches next page of results

Response

json
{
  "results": [
    {
      "orderId": "ORD-2024-001",
      "displayDate": "15-04-2024 14:30",
      "date": "2024-04-15 14:30:00",
      "timestamp": 1713190200,
      "email": "user@example.com",
      "sourceOrderId": "INV-2024-12345",
      "orders": [
        {
          "title": "Family Vacation 2024",
          "coverPreview": "https://cdn.example.com/preview.jpg",
          "quantity": 2,
          "total": 59.98,
          "product": {
            "name": "Premium Photo Book",
            "basePrice": 29.99,
            "extraCostPerPage": 0.50
          },
          "displayStatus": "Processing"
        }
      ],
      "orderStatus": "Payment Complete",
      "shippingAddress": {
        "firstname": "John",
        "lastname": "Doe",
        "address_1": "123 Main Street",
        "city": "New York",
        "postcode": "10001",
        "country": "United States"
      },
      "shippingCost": 5.99,
      "voucher": "SAVE10",
      "voucherAmount": 6.00,
      "subTotal": 59.98,
      "grandTotal": 59.97
    }
  ],
  "cursor": "next-page-token"
}

Response Fields

Top-Level Fields

FieldTypeDescription
resultsarrayArray of order objects (max 10 per request)
cursorstringToken for fetching next page. Undefined if no more results

Order Object

FieldTypeDescription
displayDatestringFormatted date for display (DD-MM-YYYY HH:mm)
timestampintegerUnix timestamp in seconds (recommended for timezone conversion)
sourceOrderIdstringInvoice/reference order ID for display
ordersarrayLine items in the order
orderStatusstringPayment status
shippingAddressobjectDelivery address
shippingCostfloatShipping charges
voucherstringCoupon/voucher code used (if any)
voucherAmountfloatDiscount amount from voucher
subTotalfloatSubtotal before shipping and discounts
grandTotalfloatFinal total amount paid

Line Item (orders array)

FieldTypeDescription
titlestringPhotobook title
coverPreviewstringURL to cover thumbnail image
quantityintegerNumber of copies ordered
totalfloatTotal cost for this line item
product.namestringProduct name
product.basePricefloatBase price of product
product.extraCostPerPagefloatCost per additional page
displayStatusstringOrder fulfillment status (e.g., "Processing", "Shipped")

Shipping Address

FieldTypeDescription
firstnamestringFirst name
lastnamestringLast name
address_1stringAddress line 1
address_2stringAddress line 2 (optional)
citystringCity
postcodestringPostal/ZIP code
statestringState/province
countrystringCountry name

Pagination

The API returns a maximum of 10 orders per request. Use the cursor field to fetch additional pages.

How Pagination Works

  1. Make initial request without cursor
  2. Display the 10 results
  3. If response includes a cursor, there are more results
  4. Make next request with the cursor value
  5. Repeat until cursor is undefined

⚠️ Important

  • results may be empty even if cursor is returned
  • Always check for cursor to determine if more pages exist
  • Continue fetching as long as cursor is present

Pagination Strategies

Lazy Loading (Recommended):

javascript
// Load initial page
const firstPage = await getOrderHistory(email);
displayOrders(firstPage.results);

// Load more when user scrolls to bottom
if (firstPage.cursor) {
  window.addEventListener('scroll', () => {
    if (isScrolledToBottom() && !loading) {
      loadMoreOrders(firstPage.cursor);
    }
  });
}

Load All Pages:

javascript
async function getAllOrders(email) {
  let allOrders = [];
  let cursor = null;
  
  do {
    const page = await getOrderHistory(email, cursor);
    allOrders = allOrders.concat(page.results);
    cursor = page.cursor;
  } while (cursor);
  
  return allOrders;
}

Example Implementation

javascript
async function getOrderHistory(email, cursor = null) {
  const requestData = {
    env: 'dev',
    key: 'your-api-key',
    marketId: 0,
    language: 'en',
    email: email
  };
  
  // Add cursor if provided
  if (cursor) {
    requestData.cursor = cursor;
  }
  
  const response = await fetch('https://{ecomm}.photobook.ai/api/v2/user/get-order-history.php', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(requestData)
  });
  
  return await response.json();
}

// Display orders in UI
async function displayUserOrders(email) {
  const { results, cursor } = await getOrderHistory(email);
  
  results.forEach(order => {
    console.log(`Order ${order.sourceOrderId}`);
    console.log(`Date: ${order.displayDate}`);
    console.log(`Total: ${order.grandTotal}`);
    console.log(`Status: ${order.orderStatus}`);
    
    order.orders.forEach(item => {
      console.log(`  - ${item.title} (${item.quantity}x) - ${item.displayStatus}`);
    });
  });
  
  // Check if more pages exist
  if (cursor) {
    console.log('More orders available. Call with cursor:', cursor);
  }
}

Timezone Considerations

The displayDate field uses server timezone. For better user experience:

  1. Use the timestamp field (Unix timestamp in seconds)
  2. Convert to user's local timezone
  3. Format according to user's locale
javascript
function formatOrderDate(timestamp) {
  const date = new Date(timestamp * 1000); // Convert to milliseconds
  return date.toLocaleDateString(navigator.language, {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit'
  });
}

Suggested Practices

  1. Implement Lazy Loading: Don't load all pages at once; load as needed
  2. Show Loading States: Display indicators during pagination
  3. Handle Empty Results: Check if results array is empty before rendering
  4. Display Status Clearly: Use displayStatus for displaying the order's current status
  5. Link to Details: Consider linking to a detailed order view for each order

photobook.ai Developer Documentation