Skip to main content

Shopify API Reference

All public store endpoints are unauthenticated — L402 payment proof serves as authorization. Admin endpoints require your Lightning Enable API key.

Base URL: https://api.lightningenable.com


Public Endpoints

These endpoints are accessible without an API key. The {slug} parameter is the URL-safe identifier you chose when creating the integration.

Get Catalog

Fetches the product catalog from your Shopify store. Results are cached.

GET /api/shopify/{slug}/catalog

Response: 200 OK

{
"storeName": "your-store.com",
"slug": "your-store",
"shipping": {
"domesticUsd": 5.99,
"domesticOnly": true,
"freeShippingEnabled": true,
"freeShippingThresholdUsd": 50.00
},
"products": [
{
"productId": 8234567890123,
"title": "Premium Coffee Beans",
"description": "Single-origin Ethiopian coffee, light roast",
"imageUrl": "https://cdn.shopify.com/s/files/...",
"variants": [
{
"variantId": 44567890123456,
"title": "12oz Bag",
"priceUsd": 18.99,
"available": true
},
{
"variantId": 44567890123457,
"title": "2lb Bag",
"priceUsd": 34.99,
"available": true
}
]
}
]
}

Error Responses:

StatusMeaning
404Integration not found or inactive

Create Checkout

Creates an L402 checkout with a Lightning invoice. Returns HTTP 402 with the payment challenge.

POST /api/shopify/{slug}/checkout

Request Body:

{
"items": [
{ "variantId": 44567890123456, "quantity": 2 },
{ "variantId": 44567890123457, "quantity": 1 }
]
}

Validation Rules:

  • 1–10 items per checkout
  • Each item quantity: 1–10
  • Total quantity across all items: max 10
  • All variant IDs must exist in the catalog
  • All variants must be available (in stock)

Response: 402 Payment Required

The response includes a WWW-Authenticate header with the L402 challenge:

WWW-Authenticate: L402 macaroon="...", invoice="lnbc..."

Response Body:

{
"orderId": "shpfy_a1b2c3d4e5f6",
"items": [
{
"variantId": 44567890123456,
"productTitle": "Premium Coffee Beans",
"variantTitle": "12oz Bag",
"quantity": 2,
"priceUsd": 18.99
},
{
"variantId": 44567890123457,
"productTitle": "Premium Coffee Beans",
"variantTitle": "2lb Bag",
"quantity": 1,
"priceUsd": 34.99
}
],
"subtotalUsd": 72.97,
"shippingUsd": 0.00,
"totalUsd": 72.97,
"totalSats": 72150,
"claimToken": "SC-x7k9m2p4",
"claimExpiresAt": "2026-03-05T18:30:00Z",
"invoice": "lnbc721500n1pn...",
"macaroonBase64": "AgELbGlnaHRuaW5n...",
"paymentHash": "a1b2c3d4e5f6...",
"invoiceExpiresAt": "2026-02-26T18:40:00Z"
}

Key Fields:

  • invoice — BOLT11 Lightning invoice to pay
  • macaroonBase64 — L402 macaroon (save this for the claim step)
  • paymentHash — links the macaroon to the invoice
  • claimToken — used to claim the order with shipping details (configurable expiry, default 30 days)
  • totalSats — BTC amount locked at current exchange rate

Error Responses:

StatusMeaning
400Invalid cart (bad variant ID, unavailable item, exceeds limits)
404Integration not found

Claim Order

Claims an order after payment: verifies L402 proof, saves shipping details, and creates a Shopify order.

POST /api/shopify/{slug}/claim

Headers:

Authorization: L402 {macaroonBase64}:{preimageHex}
Content-Type: application/json

The Authorization header format is L402 <macaroon>:<preimage>:

  • macaroon — the macaroonBase64 from the checkout response
  • preimage — the 64-character hex preimage obtained after paying the invoice

Request Body:

{
"claimToken": "SC-x7k9m2p4",
"email": "customer@example.com",
"shippingAddress": {
"firstName": "Jane",
"lastName": "Doe",
"address1": "123 Main St",
"address2": "Apt 4B",
"city": "Austin",
"province": "TX",
"zip": "78701",
"country": "US",
"phone": "+15125551234"
}
}

Shipping Address Fields:

FieldRequiredMax Length
firstNameYes200
lastNameYes200
address1Yes500
address2No500
cityYes100
provinceNo100
zipNo20
countryYes100
phoneNo30

Response: 200 OK

{
"orderId": "shpfy_a1b2c3d4e5f6",
"status": "PaidWithDetails",
"shopifyOrderNumber": "#1042",
"message": "Order #1042 created successfully. You'll receive shipping confirmation at customer@example.com."
}

Error Responses:

StatusMeaning
400Invalid claim token, expired token, already claimed, invalid L402 proof
401L402 verification failed
404Claim token not found

Get Order Status

Check the status of an order. Requires the claim token as a query parameter.

GET /api/shopify/{slug}/orders/{orderId}?claimToken={claimToken}

Response: 200 OK

{
"orderId": "shpfy_a1b2c3d4e5f6",
"status": "Shipped",
"totalUsd": 72.97,
"paidSats": 72150,
"shopifyOrderNumber": "#1042",
"trackingNumber": "1Z999AA10123456784",
"trackingCarrier": "UPS",
"trackingUrl": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
"createdAt": "2026-02-26T18:30:00Z",
"paidAt": "2026-02-26T18:31:15Z",
"shippedAt": "2026-02-28T14:22:00Z"
}

Error Responses:

StatusMeaning
401Claim token doesn't match the order
404Order not found

Merchant Admin Endpoints

These endpoints require your Lightning Enable API key in the X-API-Key header.

Get Integration

GET /api/merchant/shopify

Returns your Shopify integration configuration. The Admin API token is never returned — only hasAdminApiToken: true/false.

Create Integration

POST /api/merchant/shopify

See Setup Guide for the full request schema.

Update Integration

PUT /api/merchant/shopify

Partial update — include only the fields you want to change.

{
"domesticShippingUsd": 6.99,
"freeShippingEnabled": true,
"isActive": false,
"listInRegistry": true,
"registryCategories": "[\"commerce\",\"food-and-beverage\"]",
"registryDescription": "Your store description for agent discovery."
}

Invalidate Cache

POST /api/merchant/shopify/invalidate-cache

Forces a refresh of the cached product catalog on the next request.

List Orders

GET /api/merchant/shopify/orders
GET /api/merchant/shopify/orders?status=PaidWithDetails
GET /api/merchant/shopify/orders?page=2&pageSize=10

Query Parameters:

ParameterDefaultDescription
status(all)Filter by status: PendingPayment, PaidAwaitingDetails, PaidWithDetails, Fulfilled, Shipped
page1Page number
pageSize20Results per page

Response:

[
{
"orderId": "shpfy_a1b2c3d4e5f6",
"status": "PaidWithDetails",
"totalUsd": 72.97,
"paidSats": 72150,
"email": "customer@example.com",
"shopifyOrderNumber": "#1042",
"createdAt": "2026-02-26T18:30:00Z"
}
]

Complete Purchase Flow Example

Here's the full flow using curl:

# 1. Browse products
CATALOG=$(curl -s https://api.lightningenable.com/api/shopify/my-store/catalog)
echo "$CATALOG" | jq '.products[0].variants[0]'

# 2. Create checkout (get variant ID from catalog)
CHECKOUT=$(curl -s -X POST https://api.lightningenable.com/api/shopify/my-store/checkout \
-H "Content-Type: application/json" \
-d '{"items": [{"variantId": 44567890123456, "quantity": 1}]}')

# Extract the invoice and macaroon
INVOICE=$(echo "$CHECKOUT" | jq -r '.invoice')
MACAROON=$(echo "$CHECKOUT" | jq -r '.macaroonBase64')
CLAIM_TOKEN=$(echo "$CHECKOUT" | jq -r '.claimToken')

# 3. Pay the invoice (using Lightning Enable MCP, lncli, or any Lightning wallet)
# This gives you the preimage (64 hex chars)
PREIMAGE="your_preimage_hex_here"

# 4. Claim the order
curl -X POST https://api.lightningenable.com/api/shopify/my-store/claim \
-H "Content-Type: application/json" \
-H "Authorization: L402 ${MACAROON}:${PREIMAGE}" \
-d "{
\"claimToken\": \"${CLAIM_TOKEN}\",
\"email\": \"customer@example.com\",
\"shippingAddress\": {
\"firstName\": \"Jane\",
\"lastName\": \"Doe\",
\"address1\": \"123 Main St\",
\"city\": \"Austin\",
\"province\": \"TX\",
\"zip\": \"78701\",
\"country\": \"US\"
}
}"

# 5. Check order status
curl "https://api.lightningenable.com/api/shopify/my-store/orders/shpfy_abc123?claimToken=${CLAIM_TOKEN}"

Edge Cases

ScenarioWhat Happens
BTC price moves after checkoutThe sats amount is locked in the Lightning invoice at checkout time. The invoice expires in ~10 minutes.
Product goes out of stockChecked at checkout time against cached catalog. At claim time, Shopify's decrement_obeying_policy handles inventory.
Claim token used twiceSecond claim is rejected — tokens are single-use.
Shopify order creation failsOrder stays in PaidAwaitingDetails. Payment is safe. Can be retried via admin.
Invoice expires before paymentOrder stays in PendingPayment. Agent must create a new checkout.
Claim token expiresContact the merchant for manual resolution. Payment is recorded. Default expiry is 30 days (configurable).