# Lightning Enable Store - AI Agent Skills

> Document version: 2026-10-15. MCP tool names verified against the released Lightning Enable MCP server v2.1.0 (default `standard` tool profile). Claim contract: `Authorization: L402 <macaroon>:<preimage>` header.

This document helps AI agents (Claude, GPT, and others) buy from the Lightning Enable Store with the Lightning Enable MCP server. Store purchasing is described here in full. Wallet and MCP installation are not: they live in one place, linked below, so this page can't drift out of date.

**Design your own T-shirt (beta).** Design your own T-shirt from an uploaded PNG, paid over L402, with a Printful mockup and human approval. The recommended way for an agent to do it is the open [`design-a-shirt` skill](https://github.com/refined-element/lightning-enable-skills/tree/main/skills/design-a-shirt); the raw steps are under [Custom products (beta)](#custom-products-beta) below.

The MCP server also includes `discover_api`, which searches the L402 API registry for other paid APIs by keyword or category.

## Prerequisites

Your agent needs the **Lightning Enable MCP server** connected to a Lightning wallet that **returns a preimage** (proof of payment). The store claim step can't work without it.

- **Set up the MCP server and a wallet:** follow the [agent-wallet-setup skill](https://github.com/refined-element/lightning-enable-skills/tree/main/skills/agent-wallet-setup), which installs the MCP on your host, connects a wallet, sets a spend ceiling, and proves the loop with a 1-sat L402 payment. Reference pages: [MCP quick start](https://docs.lightningenable.com/products/agentic-commerce/mcp-quickstart) and [wallet configuration](https://docs.lightningenable.com/products/agentic-commerce/mcp-wallet-setup).
- **Check the wallet from the agent:** `setup_wallet` reports which wallet is configured, and `test_l402_payment` self-tests it against a public 1-sat L402 endpoint.
- **Wallet compatibility:** the [wallet configuration page](https://docs.lightningenable.com/products/agentic-commerce/mcp-wallet-setup) lists which wallets return preimages. OpenNode does not, so it can't complete a store purchase.

Lightning Enable does not hold funds. Your wallet or payment provider holds your balance and settles the payment.

## MCP tools used in a store purchase

| Tool | Used for |
|------|----------|
| `get_balance` | Check you have enough sats before checkout |
| `budget(action="status")` | Check your spending limits and what this session has already spent |
| `pay_invoice` | Pay the BOLT11 invoice from the checkout response and get the preimage |
| `receipts(source="durable")` | Look up the payment afterwards (the receipt log never contains the preimage) |
| `verify_confirmation_code` | Only verifies a confirmation code; it never pays. See "Budget and confirmation" |

The full, current tool list is in the [MCP complete guide](https://docs.lightningenable.com/products/agentic-commerce/mcp-complete-guide).

## Purchasing from the store

### Step 1: Browse the catalog

```
GET https://store.lightningenable.com/api/store/catalog
```

Returns all products with prices in satoshis and USD. The response includes both **official Lightning Enable merchandise** (ids 1–4) and **Community Collection** designs (ids ≥ 1000) in the same `products` array. Both purchase through identical endpoints, with no special handling.

Community products carry a `description` with the designer's own text. Surface it to your user before checkout.

### Step 2: Check your balance and budget

Call `get_balance` and `budget(action="status")`. A t-shirt costs tens of thousands of sats, so make sure both the balance and the remaining per-payment and per-session limits cover the total.

### Step 3: Create a checkout

```
POST https://store.lightningenable.com/api/store/checkout
Content-Type: application/json

{
  "items": [
    {"productId": 1, "quantity": 1, "size": "L", "color": "Black"}
  ]
}
```

You receive HTTP 402. The `l402` object in the body holds:
- `invoice`: the BOLT11 Lightning invoice
- `macaroon`: the L402 macaroon
- `amountSats`: the total in satoshis
- `paymentHash`: the invoice's payment hash

### Step 4: Pay the invoice

Call `pay_invoice` with the BOLT11 `invoice` string. It returns the `preimage` (proof of payment).

### Step 5: Claim the order

Send the macaroon and preimage in the `Authorization` header. No request body is needed.

```
POST https://store.lightningenable.com/api/store/claim
Authorization: L402 {macaroon}:{preimage}
```

The response holds a `claimUrl` for the human to enter shipping details. Treat the macaroon, the preimage, and the claim URL as secrets: don't paste them into logs, issue trackers, or chat transcripts that other people can read.

The older `l402Credential` JSON body field is deprecated; send the credential only in the header. A request that carries different credentials in the header and the body field is rejected with HTTP 401.

### Step 6: Share the claim URL

Give the claim URL to your human user. They enter their shipping address, and the order is fulfilled through Printful.

## Example conversation

**Human:** "Buy me a Lightning Enable t-shirt, size large, black"

**AI agent:**
1. Calls `GET /api/store/catalog` to find the product id
2. Calls `get_balance` and `budget(action="status")` to confirm it can afford it
3. Calls `POST /api/store/checkout` with the item
4. Receives HTTP 402 with the invoice and macaroon
5. Calls `pay_invoice` with the invoice; if the amount needs confirmation, asks the human for the code (see below)
6. Gets the preimage from the payment
7. Calls `POST /api/store/claim` with `Authorization: L402 {macaroon}:{preimage}`
8. Returns the claim URL to the human

**Human receives:** "I've bought the t-shirt. Visit [claim URL] to enter your shipping address."

## Budget and confirmation

Store purchases are merchandise-scale: a single item is tens of thousands of sats. Spending limits are set by the operator in `~/.lightning-enable/config.json` and an agent can only lower them at runtime, never raise them. The authoritative reference for every limit and its default is [AI spending security](https://docs.lightningenable.com/products/agentic-commerce/ai-spending-security#sats-native-budgets); read it before changing anything.

What that means for a store purchase:

- **Confirmation is expected.** A payment of this size is above the default auto-approve tiers, so `pay_invoice` doesn't pay straight away: the MCP server sends a confirmation code to the human outside the chat (by default, on the server's console), the agent asks the human for that code, and calls `pay_invoice` again with it. That's the safety design working, not an error. The code is never returned to the agent, and `verify_confirmation_code` only checks a code; it never pays.
- **If your limits are too low for one item,** an operator can raise the per-payment ceiling to just above the item price. For example, sats-denominated limits that fit one or two items:

```json
{
  "limits": {
    "maxPerPaymentSats": 60000,
    "maxPerSessionSats": 120000
  }
}
```

When USD and sats limits are both set, the stricter one wins on every check. Keep `autoApproveSats` small (or unset): it decides what may be paid with no human in the loop, and merchandise purchases should keep the human in the loop.

## Troubleshooting

### "Insufficient balance"
Fund your Lightning wallet, then check again with `get_balance`.

### Payment refused by the budget
Call `budget(action="status")` to see which limit is binding. Raising it is an operator change to the config file; see [AI spending security](https://docs.lightningenable.com/products/agentic-commerce/ai-spending-security).

### "Invoice expired"
Invoices expire after about 10 minutes. Start a new checkout and pay promptly.

### "Invalid preimage"
The preimage must match the invoice's payment hash: `SHA256(preimage) == paymentHash`. Make sure you're using the preimage from the payment of *this* checkout's invoice.

### "Conflicting L402 credentials"
You sent the credential in both the `Authorization` header and the deprecated body field, and they differ. Send it only in the header.

### Wallet connection problems
See [wallet configuration](https://docs.lightningenable.com/products/agentic-commerce/mcp-wallet-setup).

---

## Community Collection

There are two separate flows tied to the Community Collection. Make sure you pick the right one.

### Buying a community design (no special steps)

Community designs (ids ≥ 1000) are sold through the **same** `/api/store/catalog`, `/api/store/checkout`, `/api/store/claim`, and `/api/store/cart` endpoints as the official merchandise above. The L402 flow is identical. Call `GET /api/store/catalog`, look for `id >= 1000`, and follow the standard purchase steps. No additional MCP setup, no extra credentials.

### Submitting a new design

This is for agents that want to create and publish a **new** community design. Buyers don't use these endpoints.

AI agents can submit designs to the Community Collection.

#### Submission flow

1. **Get requirements**
   ```
   GET https://store.lightningenable.com/api/community/submit/info
   ```
   Returns the fee (2,000 sats), file requirements, and product types.

2. **Initiate the submission**
   ```
   POST https://store.lightningenable.com/api/community/submit/initiate
   Content-Type: application/x-www-form-urlencoded

   DesignerName=AI+Artist&DesignerEmail=ai@example.com&DesignName=Bitcoin+Art&ProductType=TShirt
   ```
   Returns `invoice` (BOLT11) and `paymentHash`.

3. **Pay the fee (2,000 sats)**
   Call `pay_invoice` with the BOLT11 invoice.

4. **Poll for payment**
   ```
   GET https://store.lightningenable.com/api/community/submit/status/{paymentHash}
   ```
   Repeat until `paid: true`.

5. **Upload the design**
   ```
   POST https://store.lightningenable.com/api/community/submit/complete
   Content-Type: multipart/form-data

   PaymentHash={paymentHash}
   DesignFile=[design.png]
   ```
   Returns `submissionId`.

6. **Check status**
   ```
   GET https://store.lightningenable.com/api/community/submissions/{submissionId}
   ```
   Status values: Pending → Approved → Published

#### Design requirements

- **File type:** PNG only (transparent background recommended)
- **Min dimensions:** 2400×2400 pixels
- **Max file size:** 50 MB
- **Product types:** TShirt, Snapback, DadHat

---

## Custom products (beta)

Put a person's own PNG on a Classic T-Shirt. Until custom products are switched on, every `/api/store/custom/*` route answers HTTP 404 with error "custom_products_disabled"; buy from the catalog above instead. The full reference, with every response and error, is the Custom Products section of [llms-full.txt](https://store.lightningenable.com/llms-full.txt).

The recommended way to run this flow is the open [`design-a-shirt` skill](https://github.com/refined-element/lightning-enable-skills/tree/main/skills/design-a-shirt) from [lightning-enable-skills](https://github.com/refined-element/lightning-enable-skills). It follows the steps below with the Lightning Enable MCP server and keeps approval and the shipping address with the person.

**What you may do and what only the person may do.** You may upload the artwork, pay the design fee, poll, request a quote and pay for the shirt within your budget. Approving the design for manufacture is the person's decision, and so is entering the shipping address. There is no agent-approval path.

There are two payments. Show each amount to the person before you pay it:

- **Payment A, design preparation:** a fixed fee, 1,000 sats by default (`designPriceSats` in the custom catalog is the live value).
- **Payment B, the shirt:** the quote's `priceSats`. Quotes last 15 minutes.

**Artwork rules.** One PNG, at least 2400 × 2400 px and at most 12,000 × 12,000 px and 40 million pixels in total, at most 50 MB; a transparent background is recommended. The image is scaled to fit the print area, centred horizontally and top-aligned (a chest print). Before any payment the upload refuses a PNG with nothing visible (fully transparent, or under 50% opacity everywhere): `400 nothing_to_print`, failure code `NoVisibleContent`, nothing charged. It warns, without refusing, about `LowEffectiveDpi` (under 150 DPI at print size), `NoTransparency` (the background prints as a solid rectangle) and `ExcessiveEmptyMargins` (more than 40% of the canvas is empty). After Payment A, preparation can add `LowContrastWithGarment`, `ColorProfileDiscarded` and `AnimationDiscarded` on the design status. A file that still cannot be printed ends in `GenerationFailed` with `failureCode: InvalidInput`: the design fee is kept, because the free retry covers technical failures only; upload new artwork.

**`Idempotency-Key`:** use a new UUID for each new design, quote or purchase, and resend the same one on the paid retry. The listing checkout requires at least 16 characters (a UUID has 36).

**Two links go to the person, and only to them.** The approval link and the claim link carry tokens (the design claim token and the order claim token): hand each one only to the person it is for, never post or log them, and keep the tokens in the `Authorization` header in your own calls.

**Rate limits and outages:** on a 429 or 503, honour `Retry-After` (seconds) before you retry; nothing is charged twice.

### Step 1: Read the custom catalog

```
GET https://store.lightningenable.com/api/store/custom/catalog
```

Note the colors, sizes, artwork requirements (`designRequirements`, including `maximumTotalPixels` and `placementRule`; see the artwork rules above), `artworkChecks` and `designPriceSats`.

### Step 2: Upload the PNG

```
POST https://store.lightningenable.com/api/store/custom/uploads
Content-Type: multipart/form-data   (field "file")
```

Keep the `uploadId` and show the person any `warnings`. Uploading never charges; a file that fails a check (a damaged PNG, too many pixels, or "nothing_to_print" when nothing is visible) is refused here, before any invoice. One upload can start up to 5 designs and is usable for new designs for 24 hours; after that, upload it again.

### Step 3: Pay for design preparation

```
POST https://store.lightningenable.com/api/store/custom/designs
Content-Type: application/json
Idempotency-Key: <a new UUID you keep>

{"uploadId": "upl_...", "product": {"productCode": "classic-tshirt", "color": "black", "placement": "front"}}
```

The response is HTTP 402 with `l402.invoice` and `l402.macaroon`. Check `budget(action="status")`, pay the invoice with `pay_invoice`, then send the **same request again** (same body, same `Idempotency-Key`) with:

```
Authorization: L402 <macaroon>:<preimage>
```

The response is HTTP 202 with `designId` and `claimToken`. Keep the claim token private.

### Step 4: Wait for the preview

Poll every 10 seconds; polling is free:

```
GET https://store.lightningenable.com/api/store/custom/designs/{designId}
Authorization: Bearer <claimToken>
```

A Printful mockup render can take a minute or more. When `status` is `AwaitingApproval`, the response lists the preview under `mockups` (`"placeholder": false` for a Printful render) and the artwork digest under `artwork.sha256`. If `status` is `GenerationFailed`, a technical failure is retried for you at no charge; a failure code of InvalidInput (`failureCode: InvalidInput`) means the artwork itself cannot be printed: the fee is kept and it needs a new upload.

### Step 5: Ask the person to approve

Approval is the person's decision, made on the approval page. Give the person `approvalUrl` from the status with `?credential=<claimToken>` appended:

```
https://store.lightningenable.com/store/custom/design/{designId}/approve?credential=<claimToken>
```

Or give them the bare `approvalUrl` and the token to paste. There they see the preview, the product, the color and any print warnings, confirm both statements themselves (`acknowledgeRights`: they hold the rights to print and sell this artwork; `acknowledgePhysicalVariation`: printed colors and placement differ from a screen), and approve or reject. Never set these acknowledgements for them: no API route approves. Poll the status until it is `Approved`. The link holds the claim token, so share it only with that person.

### Step 6: Get a quote

Ask the person for the size, state and ZIP code only. Do not ask for, or send, a name or street address here.

```
POST https://store.lightningenable.com/api/store/custom/designs/{designId}/quotes
Authorization: Bearer <claimToken>
Idempotency-Key: <a new UUID>

{"variant": {"size": "L"}, "destination": {"countryCode": "US", "stateCode": "PA", "postalCode": "19103"}, "shippingMethod": "STANDARD"}
```

Custom products ship to the 48 contiguous states and DC. Alaska, Hawaii, US territories and APO/FPO/DPO addresses are refused with a message that says so. Shipping outside the continental US? Contact us at support@lightningenable.com and we may be able to accommodate your order.

### Step 7: Pay for the shirt and hand off

Show the person `totalUsd` and `priceSats`, then:

```
POST https://store.lightningenable.com/api/store/custom/checkout
Idempotency-Key: <a new UUID you keep>
Authorization: Bearer <design claimToken>

{"quoteId": "quo_...", "designId": "des_..."}
```

Pay the 402 invoice with `pay_invoice` and repeat the same request with `Authorization: L402 <macaroon>:<preimage>` in place of the Bearer token. The response has `claimUrl`: give it to the person, who enters the shipping address privately. The store then drafts the order at Printful, checks Printful's price against the quote and submits it once; if the price rose beyond what the quote allowed, the order stops for manual review. Follow the order with `GET /api/store/custom/orders/{orderId}` and `Authorization: Bearer <claimToken from this response>`.

If the status stays at `Claimed`, `PrintfulDraftCreated` or `PrintfulCostVerified`, the store finishes the order by itself (Printful was busy or still pricing). You can nudge it, without any address, with:

```
POST https://store.lightningenable.com/api/store/custom/orders/{orderId}/fulfill
Authorization: Bearer <claimToken from this response>
```

`409 address_required` means the person has not entered the address yet: send them the `claimUrl` again. Never put the claim token in a URL path or query; it goes only in the `Authorization` header.

### Refunds

There are no automatic Lightning refunds. The design fee covers preparation once it starts; a technical failure is retried free of charge, never charged twice. If Printful cannot make or ship the order, it goes to manual review. For exceptions, contact support@lightningenable.com with the order id.

## Designed by our customers (listings, beta)

Approved custom designs can be published as listings that anyone buys. While listings are off, the listing routes answer 404 "custom_listings_disabled".

### Find a listing

```
GET https://store.lightningenable.com/api/store/custom/listings
GET https://store.lightningenable.com/api/store/custom/listings/{listingId}
```

Each listing has `listingId`, `title`, `product` (code, name, color, sizes), `listingUrl` (the page for a person), `mockupUrl` and `checkoutUrl`. The store catalog (`GET /api/store/catalog`) lists them under `customListings`.

### Buy a listing

1. Ask the person for the size and their state and ZIP (never a street address).
2. Request the checkout:

```
POST https://store.lightningenable.com/api/store/custom/listings/{listingId}/checkout
Idempotency-Key: <a new UUID for this purchase>
Content-Type: application/json

{"size": "L", "quantity": 1, "destinationScope": "US-PA-191"}
```

The `Idempotency-Key` must be at least 16 characters (use a new UUID per purchase, and resend it on the paid retry). `destinationScope` is `US-{state}-{first three ZIP digits}`; you can send `"destination": {"countryCode": "US", "stateCode": "PA", "postalCode": "19103"}` instead. The answer is HTTP 402 with your own fresh quote and the invoice (`l402.invoice`, `l402.amountSats`, `l402.macaroon`).
3. Show the person the total in sats, pay with `pay_invoice`, then repeat the exact request (same body, same key) with `Authorization: L402 <macaroon>:<preimage>`. You get `claimUrl` and `claimToken`.
4. Give the person the `claimUrl`; they enter the shipping address there.

`409 listing_not_available` means the listing is no longer on sale (withdrawn, taken down or expired), or, with `reason: "publishing_disabled"`, that the store paused listing sales. Nothing is charged. `429 listing_quote_limit`: wait a minute and retry. A person can also buy on `listingUrl` with a Lightning QR code.

### Publish a design (the designer's choice)

Only after the person approved the design on the approval page, and only if they want it sold to others:

```
POST https://store.lightningenable.com/api/store/custom/designs/{designId}/publish
Authorization: Bearer <design claimToken>
Content-Type: application/json

{"listingTitle": "Orange Bolt Tee", "acknowledgeRights": true}
```

`acknowledgeRights: true` is the designer's statement that the artwork may be sold to other buyers: send it only after they confirmed it to you, never on your own. The answer carries `publicationStatus` ("pending_review" while the store reviews it, then `published` with `listingUrl`). `GET /api/store/custom/designs/{designId}/publication` reads it; `POST .../withdraw` takes the listing down for good. `409 publish_limit_reached` means the designer has the most listings this store allows; `409 publishing_disabled` means the store takes no new listings.

---

## Error handling

| Status | Meaning | Action |
|--------|---------|--------|
| 400 | Invalid request, or a credential that doesn't verify | Check required fields; verify the preimage matches the payment hash |
| 401 | Missing or conflicting L402 credential | Send `Authorization: L402 {macaroon}:{preimage}`, and only there |
| 402 | Payment required | Pay the Lightning invoice |
| 404 | Not found | Check ids |
| 429 | Rate limited | Honour `Retry-After` (wait 60 seconds when there is none) |

## Links

- Store: https://store.lightningenable.com
- API reference: https://store.lightningenable.com/llms-full.txt
- MCP complete guide: https://docs.lightningenable.com/products/agentic-commerce/mcp-complete-guide
- Wallet setup skill: https://github.com/refined-element/lightning-enable-skills/tree/main/skills/agent-wallet-setup
- Support: support@lightningenable.com
