Fx Print Shop Logo
WishlistShopping Cart

Developer documentation

Fx Print Shop API & Webhooks

Public reference for partners syncing orders, customers, catalog, stock, and more. Authenticate with a Bearer API key. Receive signed event webhooks when data changes.

Getting started

  1. Ask a store admin to open Dashboard → Settings → Integrations and create a connection for your system.
  2. Generate an API key and copy the webhook signing secret (shown once).
  3. Provide your HTTPS webhook URL and enable the events you need.
  4. Call the REST API with Authorization: Bearer <apiKey>.

Per-system keys

Each integration has its own API key and webhook URL.

Push + pull

Webhooks notify you of changes; REST lets you sync on demand.

Signed payloads

Verify X-FxPrint-Signature with HMAC-SHA256.

Base URL: https://fxprintshop.com

Authentication

All /api/integrations/* routes require a Bearer token. The connection must be enabled and have an API key generated.

HTTP header
Authorization: Bearer fxp_xxxxxxxxxxxxxxxx
  • Do not put the API key in query strings or client-side JavaScript.
  • Rotate the key from the dashboard if it is leaked.
  • Disabled connections reject requests even with a previously valid key.

API conventions

List query parameters

  • limit — 1–200 (default 50)
  • skip — pagination offset (default 0)
  • updatedSince — ISO-8601 timestamp; matches updatedAt or createdAt
  • lowStock=true — only on /stock

List response shape

JSON
{
  "data": [ /* array of records */ ],
  "meta": {
    "total": 123,
    "limit": 50,
    "skip": 0
  }
}

Detail response shape

JSON
{ "data": { /* single record */ } }

Dates are serialized as ISO strings. MongoDB _id values are returned as strings.

Example request
curl -sS -H "Authorization: Bearer fxp_YOUR_API_KEY" \
  "https://fxprintshop.com/api/integrations/orders?limit=20&skip=0"

REST endpoints

Read-only in the current version. There are no public create/update/delete endpoints.

MethodPathDescriptionID lookup
GET/api/integrations/ordersList orders—
GET/api/integrations/orders/{id}Single order_id or orderNumber
GET/api/integrations/customersList customers—
GET/api/integrations/customers/{id}Single customer_id or customerId
GET/api/integrations/productsList products—
GET/api/integrations/products/{id}Single product_id, productId, or slug
GET/api/integrations/categoriesList categories—
GET/api/integrations/categories/{id}Single category_id or categoryId
GET/api/integrations/brandsList brands—
GET/api/integrations/brands/{id}Single brand_id or brandId
GET/api/integrations/shipping-methodsList shipping methods—
GET/api/integrations/shipping-methods/{id}Single method_id or shippingMethodId
GET/api/integrations/stockStock snapshot (?lowStock=true)—
GET/api/integrations/stock/{id}Stock + history_id, productId, or slug
GET/api/integrations/promotionsList promotions—
GET/api/integrations/promotions/{id}Single promotion_id, promotionId, or code
GET/api/integrations/returnsList returns—
GET/api/integrations/returns/{id}Single return_id or returnRequestId
GET/api/integrations/service-requestsList service requests—
GET/api/integrations/service-requests/{id}Single request_id or serviceRequestId
GET/api/integrations/webhook-logsDelivery log (recent)—

Example payloads

Every list endpoint returns { data, meta }. Every detail endpoint returns { data }. Below are representative records for each resource.

Orders

GET /api/integrations/orders · GET /api/integrations/orders/{id}

GET /orders (list)
{
  "data": [
    {
      "_id": "66f1a2b3c4d5e6f7a8b9c0d1",
      "orderNumber": "ORD-1001",
      "customer": {
        "fullName": "Jane Doe",
        "email": "jane@example.com",
        "firebaseUid": "firebase_uid_abc",
        "customerId": "CUST-1001"
      },
      "shippingAddress": {
        "fullName": "Jane Doe",
        "mobile": "+201000000000",
        "street": "12 Nile St",
        "landmark": "Near metro",
        "city": "Nasr City",
        "governorate": "Cairo",
        "isPrimary": true
      },
      "items": [
        {
          "productId": "PROD-1001",
          "name": "Photo Print 8x10",
          "sku": "PP-810",
          "price": 120,
          "quantity": 2,
          "productType": "Custom Prints",
          "product": { "image": "https://cdn.example.com/p1.jpg" },
          "variationId": "var_1",
          "variationDetails": {
            "variationId": "var_1",
            "variationSku": "PP-810-GLOSS",
            "variationPrice": 120,
            "options": [
              { "typeName": "Finish", "optionValue": "Glossy", "optionName": "Glossy" }
            ]
          }
        }
      ],
      "subtotal": 240,
      "shippingCost": 40,
      "giftWrapping": false,
      "giftWrappingCost": 0,
      "discountAmount": 0,
      "vatAmount": 0,
      "vatRate": 0,
      "vatCalculationMethod": "exclusive",
      "total": 280,
      "shippingMethod": {
        "_id": "66f1ship0000000000000001",
        "name": "Standard Delivery",
        "price": 40,
        "shippingMethodId": "SHIP-1001",
        "estimatedDelivery": "2-4 business days"
      },
      "status": "Pending",
      "paymentMethod": "Cash on Delivery",
      "paymentStatus": "Unpaid",
      "orderNote": "",
      "statusHistory": [
        {
          "status": "Pending",
          "changedAt": "2026-09-07T12:00:00.000Z",
          "comment": "Order created"
        }
      ],
      "hasRefund": false,
      "createdAt": "2026-09-07T12:00:00.000Z",
      "updatedAt": "2026-09-07T12:00:00.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "limit": 50,
    "skip": 0
  }
}
GET /orders/{id} (detail)
{
  "data": {
    "_id": "66f1a2b3c4d5e6f7a8b9c0d1",
    "orderNumber": "ORD-1001",
    "customer": {
      "fullName": "Jane Doe",
      "email": "jane@example.com",
      "firebaseUid": "firebase_uid_abc",
      "customerId": "CUST-1001"
    },
    "shippingAddress": {
      "fullName": "Jane Doe",
      "mobile": "+201000000000",
      "street": "12 Nile St",
      "landmark": "Near metro",
      "city": "Nasr City",
      "governorate": "Cairo",
      "isPrimary": true
    },
    "items": [
      {
        "productId": "PROD-1001",
        "name": "Photo Print 8x10",
        "sku": "PP-810",
        "price": 120,
        "quantity": 2,
        "productType": "Custom Prints",
        "product": { "image": "https://cdn.example.com/p1.jpg" },
        "variationId": "var_1",
        "variationDetails": {
          "variationId": "var_1",
          "variationSku": "PP-810-GLOSS",
          "variationPrice": 120,
          "options": [
            { "typeName": "Finish", "optionValue": "Glossy", "optionName": "Glossy" }
          ]
        }
      }
    ],
    "subtotal": 240,
    "shippingCost": 40,
    "giftWrapping": false,
    "giftWrappingCost": 0,
    "discountAmount": 0,
    "vatAmount": 0,
    "vatRate": 0,
    "vatCalculationMethod": "exclusive",
    "total": 280,
    "shippingMethod": {
      "_id": "66f1ship0000000000000001",
      "name": "Standard Delivery",
      "price": 40,
      "shippingMethodId": "SHIP-1001",
      "estimatedDelivery": "2-4 business days"
    },
    "status": "Pending",
    "paymentMethod": "Cash on Delivery",
    "paymentStatus": "Unpaid",
    "orderNote": "",
    "statusHistory": [
      {
        "status": "Pending",
        "changedAt": "2026-09-07T12:00:00.000Z",
        "comment": "Order created"
      }
    ],
    "hasRefund": false,
    "createdAt": "2026-09-07T12:00:00.000Z",
    "updatedAt": "2026-09-07T12:00:00.000Z"
  }
}

Customers

GET /api/integrations/customers · GET /api/integrations/customers/{id}

GET /customers (list)
{
  "data": [
    {
      "_id": "66f1cust0000000000000001",
      "customerId": "CUST-1001",
      "firebaseUid": "firebase_uid_abc",
      "fullName": "Jane Doe",
      "email": "jane@example.com",
      "status": "active",
      "addresses": [
        {
          "fullName": "Jane Doe",
          "mobile": "+201000000000",
          "street": "12 Nile St",
          "landmark": "Near metro",
          "city": "Nasr City",
          "governorate": "Cairo",
          "isPrimary": true
        }
      ],
      "wishlist": ["photo-print-8x10"],
      "images": [],
      "createdAt": "2026-09-01T10:00:00.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "limit": 50,
    "skip": 0
  }
}
GET /customers/{id}
{
  "data": {
    "_id": "66f1cust0000000000000001",
    "customerId": "CUST-1001",
    "firebaseUid": "firebase_uid_abc",
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "status": "active",
    "addresses": [
      {
        "fullName": "Jane Doe",
        "mobile": "+201000000000",
        "street": "12 Nile St",
        "landmark": "Near metro",
        "city": "Nasr City",
        "governorate": "Cairo",
        "isPrimary": true
      }
    ],
    "wishlist": ["photo-print-8x10"],
    "images": [],
    "createdAt": "2026-09-01T10:00:00.000Z"
  }
}

Products

GET /api/integrations/products · GET /api/integrations/products/{id}

GET /products (list)
{
  "data": [
    {
      "_id": "66f1prod0000000000000001",
      "productId": "PROD-1001",
      "name": "Photo Print 8x10",
      "slug": "photo-print-8x10",
      "htmlDescription": "<p>High quality photo print</p>",
      "sku": "PP-810",
      "productType": "Custom Prints",
      "basePrice": 120,
      "salePrice": null,
      "categoryIds": ["66f1cat0000000000000001"],
      "brandId": "66f1brand000000000000001",
      "images": ["https://cdn.example.com/p1.jpg"],
      "tags": ["print", "photo"],
      "status": "Published",
      "trackStock": true,
      "allowBackorders": false,
      "stockQuantity": 50,
      "lowStockThreshold": 10,
      "hasVariations": true,
      "variationTypes": [
        {
          "_id": "vt1",
          "name": "Finish",
          "displayName": "Finish",
          "isRequired": true,
          "order": 0,
          "options": [
            {
              "_id": "opt1",
              "name": "Glossy",
              "value": "Glossy",
              "priceAdjustment": 0,
              "stockQuantity": 30,
              "isActive": true
            }
          ]
        }
      ],
      "variations": [
        {
          "_id": "var_1",
          "variationId": "var_1",
          "options": [{ "typeName": "Finish", "optionValue": "Glossy" }],
          "price": 120,
          "sku": "PP-810-GLOSS",
          "stockQuantity": 30,
          "isActive": true
        }
      ],
      "createdAt": "2026-08-15T09:00:00.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "limit": 50,
    "skip": 0
  }
}
GET /products/{id}
{
  "data": {
    "_id": "66f1prod0000000000000001",
    "productId": "PROD-1001",
    "name": "Photo Print 8x10",
    "slug": "photo-print-8x10",
    "htmlDescription": "<p>High quality photo print</p>",
    "sku": "PP-810",
    "productType": "Custom Prints",
    "basePrice": 120,
    "salePrice": null,
    "categoryIds": ["66f1cat0000000000000001"],
    "brandId": "66f1brand000000000000001",
    "images": ["https://cdn.example.com/p1.jpg"],
    "tags": ["print", "photo"],
    "status": "Published",
    "trackStock": true,
    "allowBackorders": false,
    "stockQuantity": 50,
    "lowStockThreshold": 10,
    "hasVariations": true,
    "variationTypes": [
      {
        "_id": "vt1",
        "name": "Finish",
        "displayName": "Finish",
        "isRequired": true,
        "order": 0,
        "options": [
          {
            "_id": "opt1",
            "name": "Glossy",
            "value": "Glossy",
            "priceAdjustment": 0,
            "stockQuantity": 30,
            "isActive": true
          }
        ]
      }
    ],
    "variations": [
      {
        "_id": "var_1",
        "variationId": "var_1",
        "options": [{ "typeName": "Finish", "optionValue": "Glossy" }],
        "price": 120,
        "sku": "PP-810-GLOSS",
        "stockQuantity": 30,
        "isActive": true
      }
    ],
    "createdAt": "2026-08-15T09:00:00.000Z"
  }
}

Categories

GET /categories/{id}
{
  "data": {
    "_id": "66f1cat0000000000000001",
    "categoryId": "CAT-1001",
    "name": "Photo Prints",
    "description": "Printed photos",
    "parentId": null,
    "image": "https://cdn.example.com/cat.jpg",
    "isActive": true,
    "createdAt": "2026-08-01T08:00:00.000Z"
  }
}

Brands

GET /brands/{id}
{
  "data": {
    "_id": "66f1brand000000000000001",
    "brandId": "BRAND-1001",
    "name": "FxPrint",
    "description": "House brand",
    "logo": "https://cdn.example.com/logo.png",
    "isActive": true,
    "createdAt": "2026-08-01T08:00:00.000Z"
  }
}

Shipping methods

GET /shipping-methods/{id}
{
  "data": {
    "_id": "66f1ship0000000000000001",
    "shippingMethodId": "SHIP-1001",
    "name": "Standard Delivery",
    "price": 40,
    "estimatedDelivery": "2-4 business days",
    "createdAt": "2026-08-01T08:00:00.000Z"
  }
}

Stock

GET /api/integrations/stock returns stock fields only. GET /api/integrations/stock/{id} adds recent history.

GET /stock (list item)
{
  "data": [
    {
      "_id": "66f1prod0000000000000001",
      "productId": "PROD-1001",
      "name": "Photo Print 8x10",
      "slug": "photo-print-8x10",
      "trackStock": true,
      "allowBackorders": false,
      "stockQuantity": 50,
      "lowStockThreshold": 10,
      "createdAt": "2026-08-15T09:00:00.000Z",
      "updatedAt": "2026-09-07T11:00:00.000Z",
      "variations": [
        {
          "_id": "var_1",
          "sku": "PP-810-GLOSS",
          "name": "Glossy",
          "stockQuantity": 30
        }
      ]
    }
  ],
  "meta": {
    "total": 1,
    "limit": 50,
    "skip": 0
  }
}
GET /stock/{id}
{
  "data": {
    "_id": "66f1prod0000000000000001",
    "productId": "PROD-1001",
    "name": "Photo Print 8x10",
    "slug": "photo-print-8x10",
    "trackStock": true,
    "allowBackorders": false,
    "stockQuantity": 50,
    "lowStockThreshold": 10,
    "variations": [
      {
        "_id": "var_1",
        "sku": "PP-810-GLOSS",
        "name": "Glossy",
        "stockQuantity": 30
      }
    ],
    "history": [
      {
        "_id": "66f1hist0000000000000001",
        "productId": "PROD-1001",
        "productName": "Photo Print 8x10",
        "variationId": "var_1",
        "previousStock": 32,
        "newStock": 30,
        "change": -2,
        "type": "remove",
        "reason": "Order ORD-1001",
        "userId": "admin_uid",
        "userName": "Admin",
        "timestamp": "2026-09-07T12:05:00.000Z"
      }
    ]
  }
}

Promotions

GET /promotions/{id}
{
  "data": {
    "_id": "66f1promo000000000000001",
    "promotionId": "PROMO-1001",
    "code": "SAVE10",
    "description": "10% off",
    "discountType": "percentage",
    "discountValue": 10,
    "isActive": true,
    "startDate": "2026-09-01T00:00:00.000Z",
    "endDate": "2026-09-30T23:59:59.000Z",
    "productTags": ["print"],
    "createdAt": "2026-08-20T10:00:00.000Z"
  }
}

Returns

GET /returns/{id}
{
  "data": {
    "_id": "66f1ret00000000000000001",
    "returnRequestId": "RET-1001",
    "orderId": "66f1a2b3c4d5e6f7a8b9c0d1",
    "orderNumber": "ORD-1001",
    "customerName": "Jane Doe",
    "customerEmail": "jane@example.com",
    "customerId": "firebase_uid_abc",
    "items": [
      {
        "productId": "PROD-1001",
        "name": "Photo Print 8x10",
        "sku": "PP-810",
        "quantity": 1,
        "reason": "Damaged in shipping"
      }
    ],
    "status": "Pending",
    "refundAmount": 120,
    "refundMethod": "Credit Card",
    "refundStatus": "Pending",
    "createdAt": "2026-09-08T09:00:00.000Z",
    "updatedAt": "2026-09-08T09:00:00.000Z"
  }
}

Service requests

GET /service-requests/{id}
{
  "data": {
    "_id": "66f1srv00000000000000001",
    "serviceRequestId": "Req-1001",
    "customerName": "Jane Doe",
    "companyName": "Acme Co",
    "phoneNumber": "+201000000000",
    "email": "jane@example.com",
    "customerId": "firebase_uid_abc",
    "serviceTypeId": "66f1stype000000000000001",
    "serviceTypeName": "On-site Printing",
    "preferredDateTime": "2026-09-15T14:00:00.000Z",
    "notes": "Bring samples",
    "serviceAddress": {
      "street": "12 Nile St",
      "landmark": "Near metro",
      "city": "Nasr City",
      "governorate": "Cairo"
    },
    "locationPin": { "lat": 30.0444, "lng": 31.2357 },
    "cost": 500,
    "status": "New",
    "replies": [],
    "createdAt": "2026-09-07T16:00:00.000Z"
  }
}

Webhook logs

GET /webhook-logs
{
  "data": [
    {
      "_id": "66f1log00000000000000001",
      "event": "order.created",
      "success": true,
      "statusCode": 200,
      "webhookUrl": "https://partner.example.com/hooks/fxprint",
      "connectionId": "int_abc123",
      "connectionName": "Your ERP",
      "createdAt": "2026-09-07T12:00:01.000Z"
    }
  ],
  "meta": {
    "total": 1,
    "limit": 50,
    "skip": 0
  }
}

Webhooks

When an enabled event occurs, Fx Print Shop sends POST to your webhook URL for that connection. Failed deliveries are logged in the dashboard; the store action is not rolled back if your endpoint fails.

Request headers

  • Content-Type: application/json
  • X-FxPrint-Event — event name
  • X-FxPrint-Connection-Id — connection id
  • X-FxPrint-Signature — HMAC-SHA256 hex of the raw body (when a signing secret exists)
  • User-Agent: FxPrint-Webhooks/1.0

Events

EventTriggered when
order.createdOrder placed (non–credit-card) or after successful card payment
order.updatedAdmin status change or payment status update
customer.createdCustomer signup or admin creates a customer
customer.updatedProfile or admin customer update
product.createdAdmin creates a product
product.updatedAdmin updates a product
integration.testManual test from the store dashboard

Example payloads by event

Envelope is always the same; data matches the REST resource document for that entity.

order.created / order.updated
{
  "event": "order.created",
  "timestamp": "2026-09-07T12:00:00.000Z",
  "connectionId": "int_abc123",
  "connectionName": "Your ERP",
  "data": {
    "_id": "66f1a2b3c4d5e6f7a8b9c0d1",
    "orderNumber": "ORD-1001",
    "customer": {
      "fullName": "Jane Doe",
      "email": "jane@example.com",
      "firebaseUid": "firebase_uid_abc",
      "customerId": "CUST-1001"
    },
    "shippingAddress": {
      "fullName": "Jane Doe",
      "mobile": "+201000000000",
      "street": "12 Nile St",
      "landmark": "Near metro",
      "city": "Nasr City",
      "governorate": "Cairo",
      "isPrimary": true
    },
    "items": [
      {
        "productId": "PROD-1001",
        "name": "Photo Print 8x10",
        "sku": "PP-810",
        "price": 120,
        "quantity": 2,
        "productType": "Custom Prints",
        "product": { "image": "https://cdn.example.com/p1.jpg" },
        "variationId": "var_1",
        "variationDetails": {
          "variationId": "var_1",
          "variationSku": "PP-810-GLOSS",
          "variationPrice": 120,
          "options": [
            { "typeName": "Finish", "optionValue": "Glossy", "optionName": "Glossy" }
          ]
        }
      }
    ],
    "subtotal": 240,
    "shippingCost": 40,
    "giftWrapping": false,
    "giftWrappingCost": 0,
    "discountAmount": 0,
    "vatAmount": 0,
    "vatRate": 0,
    "vatCalculationMethod": "exclusive",
    "total": 280,
    "shippingMethod": {
      "_id": "66f1ship0000000000000001",
      "name": "Standard Delivery",
      "price": 40,
      "shippingMethodId": "SHIP-1001",
      "estimatedDelivery": "2-4 business days"
    },
    "status": "Pending",
    "paymentMethod": "Cash on Delivery",
    "paymentStatus": "Unpaid",
    "orderNote": "",
    "statusHistory": [
      {
        "status": "Pending",
        "changedAt": "2026-09-07T12:00:00.000Z",
        "comment": "Order created"
      }
    ],
    "hasRefund": false,
    "createdAt": "2026-09-07T12:00:00.000Z",
    "updatedAt": "2026-09-07T12:00:00.000Z"
  }
}
customer.created / customer.updated
{
  "event": "customer.created",
  "timestamp": "2026-09-07T12:00:00.000Z",
  "connectionId": "int_abc123",
  "connectionName": "Your ERP",
  "data": {
    "_id": "66f1cust0000000000000001",
    "customerId": "CUST-1001",
    "firebaseUid": "firebase_uid_abc",
    "fullName": "Jane Doe",
    "email": "jane@example.com",
    "status": "active",
    "addresses": [
      {
        "fullName": "Jane Doe",
        "mobile": "+201000000000",
        "street": "12 Nile St",
        "landmark": "Near metro",
        "city": "Nasr City",
        "governorate": "Cairo",
        "isPrimary": true
      }
    ],
    "wishlist": ["photo-print-8x10"],
    "images": [],
    "createdAt": "2026-09-01T10:00:00.000Z"
  }
}
product.created / product.updated
{
  "event": "product.created",
  "timestamp": "2026-09-07T12:00:00.000Z",
  "connectionId": "int_abc123",
  "connectionName": "Your ERP",
  "data": {
    "_id": "66f1prod0000000000000001",
    "productId": "PROD-1001",
    "name": "Photo Print 8x10",
    "slug": "photo-print-8x10",
    "htmlDescription": "<p>High quality photo print</p>",
    "sku": "PP-810",
    "productType": "Custom Prints",
    "basePrice": 120,
    "salePrice": null,
    "categoryIds": ["66f1cat0000000000000001"],
    "brandId": "66f1brand000000000000001",
    "images": ["https://cdn.example.com/p1.jpg"],
    "tags": ["print", "photo"],
    "status": "Published",
    "trackStock": true,
    "allowBackorders": false,
    "stockQuantity": 50,
    "lowStockThreshold": 10,
    "hasVariations": true,
    "variationTypes": [
      {
        "_id": "vt1",
        "name": "Finish",
        "displayName": "Finish",
        "isRequired": true,
        "order": 0,
        "options": [
          {
            "_id": "opt1",
            "name": "Glossy",
            "value": "Glossy",
            "priceAdjustment": 0,
            "stockQuantity": 30,
            "isActive": true
          }
        ]
      }
    ],
    "variations": [
      {
        "_id": "var_1",
        "variationId": "var_1",
        "options": [{ "typeName": "Finish", "optionValue": "Glossy" }],
        "price": 120,
        "sku": "PP-810-GLOSS",
        "stockQuantity": 30,
        "isActive": true
      }
    ],
    "createdAt": "2026-08-15T09:00:00.000Z"
  }
}
integration.test
{
  "event": "integration.test",
  "timestamp": "2026-09-07T12:00:00.000Z",
  "connectionId": "int_abc123",
  "connectionName": "Your ERP",
  "data": {
    "message": "This is a test webhook from FxPrint",
    "testedAt": "2026-09-07T12:00:00.000Z",
    "connectionId": "int_abc123",
    "connectionName": "Your ERP"
  }
}

Respond with 2xx quickly. Do heavy work asynchronously on your side.

Verify signatures

Always verify X-FxPrint-Signature using the webhook signing secret (not the API key). Hash the exact raw body bytes with HMAC-SHA256 and compare in constant time.

Node.js
import crypto from 'crypto';

/**
 * Verify X-FxPrint-Signature (HMAC-SHA256 of the raw request body).
 * Use the webhook signing secret shown once when the API key was generated.
 */
export function verifyFxPrintSignature(
  rawBody: string | Buffer,
  signatureHeader: string | null,
  webhookSecret: string
): boolean {
  if (!signatureHeader) return false;
  const expected = crypto
    .createHmac('sha256', webhookSecret)
    .update(rawBody)
    .digest('hex');

  try {
    const a = Buffer.from(expected, 'hex');
    const b = Buffer.from(signatureHeader, 'hex');
    if (a.length !== b.length) return false;
    return crypto.timingSafeEqual(a, b);
  } catch {
    return false;
  }
}

Data models (field reference)

Webhook data and REST responses use the store's Mongo documents. Important fields:

Order

  • orderNumber, status, paymentStatus, paymentMethod
  • customer — fullName, email, firebaseUid?, customerId?
  • shippingAddress, items[], totals (subtotal, shippingCost, vat*, total)
  • statusHistory[], createdAt, updatedAt

Customer

  • customerId, fullName, email, status (active | inactive)
  • addresses[] — fullName, mobile, street, landmark?, city, governorate, isPrimary
  • firebaseUid?, wishlist[], createdAt

Product

  • productId, name, slug, basePrice, salePrice?
  • categoryIds[], brandId?, images[], tags[]
  • Stock: trackStock, stockQuantity, lowStockThreshold, allowBackorders
  • Variations: hasVariations, variationTypes[], variations[] (price, sku, stockQuantity)

Other resources

  • Category — categoryId, name, parentId?, isActive
  • Brand — brandId, name, logo?, isActive
  • Shipping method — shippingMethodId, name, price, estimatedDelivery
  • Promotion — promotionId, code, discountType (percentage|fixed), discountValue, startDate, endDate, isActive
  • Return — returnRequestId, orderNumber, status (Pending|Approved|Rejected|Processing|Completed), refundStatus, items[]
  • Service request — serviceRequestId, status (New|In Progress|Completed|Cancelled), serviceTypeName, customer contact, address

Errors

StatusMeaning
401Missing or invalid Authorization Bearer token
403No enabled connection with an API key
404Resource not found
500Server or database error
Error body
{ "error": "Invalid API key" }

Best practices

  • Idempotently handle webhooks using event + resource id (retries may occur later).
  • Prefer updatedSince polling for catch-up, plus webhooks for near-real-time updates.
  • Store secrets in a vault; never commit API keys or webhook secrets.
  • Use HTTPS webhook endpoints only.
  • Contact the store admin if you need additional events or write access — not available in the public API yet.

Contact the store if you need an integration provisioned.