anyshop.io

Docs

REST API reference

Base URL: https://anyshop.io/api/v1. All requests need an API key from /dashboard/developer. Request and response bodies are snake_case JSON. Money is integer cents in the product's currency. Dates are ISO 8601.

CLI + MCP

GETnpx @anyshop/cli help

Zero-dep CLI mirroring the REST surface. Works with ANYSHOP_API_KEY env. Examples: `anyshop orders list --status paid`, `anyshop products create --title 'Pro' --slug pro --type serial --price-cents 4900 --currency USD`.

GETnpx @anyshop/mcp

Model Context Protocol server. Add to Claude Desktop config with the ANYSHOP_API_KEY env to manage your store conversationally — 10 tools across orders, products, customers, webhooks, and audit.

Authentication

GET/api/whoami

Verify the API key. Returns shop scoping. Use this to check that an integration is correctly configured before making mutating calls.

Example

curl -H 'Authorization: Bearer as_…' https://anyshop.io/api/whoami

Orders

GET/api/v1/orders

List orders for the authenticated shop. Cursor pagination on createdAt.

Query

  • status — pending | paid | fulfilled | partially_refunded | refunded | disputed | cancelled | voided
  • limit — 1..100 (default 50)
  • cursor — ISO 8601 timestamp; returns orders created before this

Example

curl -H 'Authorization: Bearer as_…' \
  'https://anyshop.io/api/v1/orders?status=paid&limit=20'
GET/api/v1/orders/:id

Single order with joined line items (product_title, slug, type).

POST/api/v1/orders/:id/refund

Refund an order. Idempotent — refunding an already-refunded order returns 200 with already_refunded:true. For card orders also calls Stripe Refunds API (Connect-aware, reverses platform fee).

Example

curl -X POST -H 'Authorization: Bearer as_…' \
  https://anyshop.io/api/v1/orders/abc-123/refund

Customers

GET/api/v1/customers

List shop customers. Query: email (case-insensitive exact), limit.

Audit trail

GET/api/v1/audit

Audit events for the shop. Query: action (exact), since + until (ISO 8601), limit. Useful for compliance pulls and security tooling.

Products

GET/api/v1/products

List products. Same status filter shape as orders.

Query

  • status — active | on_hold | draft | unlisted | private
  • limit — 1..100
GET/api/v1/products/:id

Single product.

PATCH/api/v1/products/:id

Partial update. Strict body — unknown fields rejected with 422. Allowed: title, description, price_cents, currency, status, delivered_message, stock_total. Audited as product.edited with the changed field list.

DELETE/api/v1/products/:id

Destroy a product. License keys cascade. Returns 409 in_use on FK conflict (active orders).

POST/api/v1/products

Create a product. Defaults: status=draft, stock_total=-1 (unlimited). Returns 201, 409 slug_taken on conflict, 422 with validation details on bad body.

Body

{
  "title": "Pro license",
  "slug": "pro",
  "type": "serial",            // serial | file | service | subscription
  "price_cents": 4900,
  "currency": "USD",
  "description": "Optional markdown.",
  "stock_total": -1,           // -1 = unlimited
  "delivered_message": "Optional message shown to buyers",
  "status": "draft"            // or "active"
}

Example

curl -X POST https://anyshop.io/api/v1/products \
  -H 'Authorization: Bearer as_…' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Pro","slug":"pro","type":"serial","price_cents":4900,"currency":"USD"}'

Webhooks (manage subscriptions)

GET/api/v1/webhooks

List webhook subscriptions for the shop.

POST/api/v1/webhooks

Create a webhook subscription. Body: { url, events: [...] }. Response includes signing_secret EXACTLY ONCE — store it; we never return it again.

Body

{
  "url": "https://your-service.example.com/anyshop",
  "events": ["order.paid", "order.fulfilled", "subscription.renewed"]
}
DELETE/api/v1/webhooks/:id

Destroy a webhook subscription.

Webhooks (your endpoint)

POSTyour webhook URL

We POST signed events to subscribed URLs. Header X-Anyshop-Signature: t=<unix>,v1=<hex>. The signature is HMAC-SHA256 over the raw request body using the signing_secret shown once when you created the webhook at /dashboard/developer.

Example

// Verify with @anyshop/webhooks
import { verify } from '@anyshop/webhooks';
const body = await req.text();
const sig = req.headers.get('x-anyshop-signature');
if (!verify(body, sig, signingSecret)) {
  return new Response('Bad signature', { status: 400 });
}
const event = JSON.parse(body);

Discovery doc: GET /api/v1 — machine-readable JSON map. Verify webhook signatures in your browser at /docs/signature-playground.