Linework Developers
EN
Get access

Guide · store:write · orders:write

Run a Bloop store

Connect your warehouse, e-commerce or spreadsheet to your Bloop store on Linework: products, stock, orders and shipping.

Scopes: store:read, store:write, orders:read, orders:write.

Payments are handled by Linework inside the app. The API never moves money: you manage the catalogue and the fulfilment, buyers pay in Linework as usual.

The endpoints#

EndpointUse
GET /storeYour store.
POST /storeCreate your store, if you do not have one yet.
PATCH /storeUpdate name, description and other store details.
GET /store/productsList your products (paginated).
POST /store/productsCreate a product.
PATCH /store/products/{id}Update a product.
DELETE /store/products/{id}Remove a product.
PATCH /store/products/{id}/stockSet the available quantity.
GET /store/ordersOrders received (paginated).
GET /store/orders/{id}One order with items and shipping address.
POST /store/orders/{id}/shipMark an order as shipped, with tracking.

1. Check your store#

curl https://api.linework.app/open/v1/store \
  -H "Authorization: Bearer $LINEWORK_API_KEY"

If you do not have a store yet, GET /store returns 404 NOT_FOUND: create it with POST /store (fields in the API Reference).

2. Create a product#

Upload the photos first with POST /media (see Post with media), then create the product with their mediaIds.

curl https://api.linework.app/open/v1/store/products \
  -H "Authorization: Bearer $LINEWORK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Linen shirt",
    "description": "100% Italian linen, made in Biella.",
    "price": 59.00,
    "currency": "EUR",
    "stock": 25,
    "sku": "SHIRT-LIN-M",
    "mediaIds": ["m_8f2c1a"]
  }'
const res = await fetch("https://api.linework.app/open/v1/store/products", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.LINEWORK_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    title: "Linen shirt",
    description: "100% Italian linen, made in Biella.",
    price: 59.0,
    currency: "EUR",
    stock: 25,
    sku: "SHIRT-LIN-M",
    mediaIds: [mediaId],
  }),
});
const product = await res.json();
import os, requests

API = "https://api.linework.app/open/v1"
s = requests.Session()
s.headers["Authorization"] = f"Bearer {os.environ['LINEWORK_API_KEY']}"

product = s.post(API + "/store/products", json={
    "title": "Linen shirt",
    "description": "100% Italian linen, made in Biella.",
    "price": 59.00,
    "currency": "EUR",
    "stock": 25,
    "sku": "SHIRT-LIN-M",
    "mediaIds": [media_id],
}, timeout=30).json()

3. Keep stock in sync#

Use the dedicated stock endpoint: it is light and does not touch the rest of the product.

curl -X PATCH https://api.linework.app/open/v1/store/products/7781/stock \
  -H "Authorization: Bearer $LINEWORK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "stock": 12 }'

A typical sync job reads quantities from your system and updates only the products that changed:

const API = "https://api.linework.app/open/v1";
const headers = { Authorization: `Bearer ${process.env.LINEWORK_API_KEY}`, "Content-Type": "application/json" };

const warehouse = { "SHIRT-LIN-M": 12, "SHIRT-LIN-L": 0 }; // from your system

let cursor = null;
do {
  const url = `${API}/store/products?limit=100${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`;
  const page = await fetch(url, { headers }).then((r) => r.json());
  for (const p of page.data) {
    const qty = warehouse[p.sku];
    if (qty !== undefined && qty !== p.stock) {
      await fetch(`${API}/store/products/${p.id}/stock`, {
        method: "PATCH", headers, body: JSON.stringify({ stock: qty }),
      });
    }
  }
  cursor = page.next_cursor;
} while (cursor);
warehouse = {"SHIRT-LIN-M": 12, "SHIRT-LIN-L": 0}  # from your system

cursor = None
while True:
    params = {"limit": 100, **({"cursor": cursor} if cursor else {})}
    page = s.get(API + "/store/products", params=params, timeout=30).json()
    for p in page["data"]:
        qty = warehouse.get(p.get("sku"))
        if qty is not None and qty != p["stock"]:
            s.patch(f"{API}/store/products/{p['id']}/stock", json={"stock": qty}, timeout=30)
    cursor = page.get("next_cursor")
    if not cursor:
        break

With stock at 0 the product stays in the catalogue as sold out. To remove it, use DELETE /store/products/{id}.

4. Read new orders#

curl "https://api.linework.app/open/v1/store/orders?limit=50" \
  -H "Authorization: Bearer $LINEWORK_API_KEY"

Orders are returned newest first. Each order has an id, a status, its items, totals and, for GET /store/orders/{id}, the shipping address. Fetch the list every few minutes and process orders that are paid and not yet shipped. The full order schema and status values are in the API Reference.

Orders contain buyers' personal data (name, address). Use it only to fulfil the order, keep it safe and do not share it. See the API Terms.

5. Mark as shipped#

curl https://api.linework.app/open/v1/store/orders/50213/ship \
  -H "Authorization: Bearer $LINEWORK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "carrier": "BRT", "trackingNumber": "084512345678" }'

The buyer is notified in the app with the tracking details. Shipping an order twice, or an order that cannot be shipped (for example cancelled), fails with 409 CONFLICT.