E-commerce Integration

Guide

Issue a tax document for every order in your store (WooCommerce, Shopify, a custom shop), keep customers matched to Glance clients, and never issue the same invoice twice.

WooCommerce: an official plugin, Glance for WooCommerce, is coming soon. It does everything on this page for you. Until it ships, or for any other platform, follow the steps below.

Overview

A typical e-commerce integration involves three data flows:

1

Customers

Match each buyer to a Glance client, or create one with the order

2

Orders

Issue an invoice-receipt (or invoice) once per order, safely retryable

3

Inventory

Read stock levels from Glance by SKU

Step 0: The API Key

Create a key with action roles only, no base role: documents.create.invoiceReceipt, documents.create.invoice, documents.create.receipt, documents.create.refund, documents.view, clients.view, clients.create, products.view, inventory.view and webhooks.manage. When the store owner pastes the key, call GET /apiKeys/me to confirm it works and to show which business it belongs to (see Verifying a Key).

Step 1: Customers

The simplest path needs no separate customer sync: send the buyer inline on the document with identifyClientBy: "email". Glance matches an existing client by exact email (case-insensitive) and otherwise creates one from the client object, with its phone number and address. An existing client is never overwritten.

To look a customer up yourself, use exactEmail (or phone) on GET /clients. The plain email filter is a substring match and can return someone else:

JavaScript
const res = await fetch(
  "https://api.glance.co.il/clients?exactEmail=" +
    encodeURIComponent(order.billing.email),
  { headers: { Authorization: `Bearer ${API_KEY}` } }
).then(r => r.json());

const clientId = res.data[0]?.id; // numeric id, usable as clientId

Step 2: Order to Invoice

When an order is paid, issue an invoiceReceipt (or an invoice when payment comes later). Two things make it safe to retry:

  • externalId: your order id, unique per company. Sending an externalId that was already used returns the document issued under it, with alreadyExists: true, instead of issuing a second one.
  • An Idempotency-Key header: the same key on every retry of one order returns the original response. See Idempotency.

Shipping is a product line like any other, so it is taxed and shows on the document. Online payment methods have their own values: bit, paypal and wallet (Apple Pay / Google Pay), next to creditCard and bankTransfer.

JavaScript
await fetch("https://api.glance.co.il/documents/create/invoiceReceipt", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `order-${order.id}`,
  },
  body: JSON.stringify({
    externalId: `woo-${order.id}`,
    client: {
      name: order.billing.name,
      email: order.billing.email,
      phoneNumber: order.billing.phone,
      address: {
        street: order.billing.address1,
        city: order.billing.city,
        zip: order.billing.postcode,
        country: order.billing.country,
      },
    },
    identifyClientBy: "email",
    taxMode: "includeTax",
    products: [
      ...order.items.map(item => ({
        description: item.name,
        sku: item.sku,
        units: item.quantity,
        price: item.price,
      })),
      { description: "Shipping", units: 1, price: order.shippingTotal },
    ],
    payments: [{
      amount: order.total,
      paymentMethod: "bit", // or "creditCard", "paypal", "wallet", ...
      date: order.paidAt.slice(0, 10),
    }],
    sendToClient: true,
  }),
});

Step 3: Reconciliation

After a timeout, or when checking which orders have a document, ask by your own id: GET /documents/by-external-id/:externalId. It returns the document, or a 404 when nothing was issued under that id, which means retrying the create is safe. It needs the documents.view action role.

GET /documents/by-external-id/woo-1042
Authorization: Bearer gk_live_...

Step 4: Inventory

Read stock with GET /inventory/product/:productId, which returns availableQuantity across every warehouse, and poll it on a schedule. Webhooks (webhooks.manage) cover documents, not stock: subscribe to document.cancelled and document.refunded to keep order statuses in step when someone acts in Glance directly.

Tip: Use GET /products/sku/:sku to look up products by their SKU, which is typically the same across your store and Glance.

Best Practices

  • Send externalId and an Idempotency-Key on every create rather than checking for an existing document first. The check-then-create race is exactly what issues the duplicate
  • Match customers with identifyClientBy: "email" or exactEmail, never with the substring email filter
  • clientId is the client's numeric id, not its visibleId
  • Use invoiceReceipt when payment is already collected
  • Always include sku in document products for inventory tracking
  • Use a key with action roles only, so a leaked store key cannot read or change anything else

Last updated