{
  "schema_version": "1.0",
  "name": "File Market",
  "description": "Catalog of bot blueprints, software, and files. Bots buy packs with Agentic Pay (fmb_). Or open Stripe Checkout for the human. Card numbers stay in Stripe.",
  "url": "https://filemarket.app",
  "version": "1.0.0",
  "provider": {
    "organization": "File Market",
    "url": "https://filemarket.app"
  },
  "auth": {
    "type": "none",
    "notes": "Public read. Buyer token debits Agentic Pay. Without a funded wallet, Checkout is a payment link; the human pays on Stripe."
  },
  "capabilities": [
    "catalog.read",
    "product.read",
    "checkout.create",
    "checkout.status"
  ],
  "payments": {
    "processor": "stripe",
    "mode": "live",
    "currency": "usd"
  },
  "mcp": {
    "transport": "http",
    "url": "https://filemarket.app/mcp",
    "docs": "https://filemarket.app/mcp",
    "auth": "none for buying tools; Authorization: Bearer fmk_… for seller tools"
  },
  "storage": {
    "canonical": "Cloudflare R2 bucket file-market",
    "downloads": "short-lived signed links through the Worker; packs are never public objects",
    "versions": "immutable per version with sha256",
    "safety": "automated checks on every version; quarantined versions never publish"
  },
  "endpoints": {
    "catalog": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/catalog"
    },
    "product": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/products/{slug}"
    },
    "invite": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/accounts/invite",
      "content_type": "application/json",
      "notes": "No password. Generic confirmation only unless you are a seller/admin. Human claims at /claim-account."
    },
    "wallet": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/wallet",
      "auth": "Bearer fmb_…"
    },
    "wallet_topup": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/wallet/topup",
      "auth": "Bearer fmb_…",
      "notes": "Returns checkout_url for the human. amount_cents 500 to 50000."
    },
    "tickets": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/tickets",
      "auth": "Bearer fmb_…"
    },
    "open_ticket": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/tickets",
      "auth": "Bearer fmb_…"
    },
    "checkout": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/checkout",
      "content_type": "application/json"
    },
    "checkout_status": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/checkout/{session_id}",
      "headers": [
        "x-agent-id: same agent_id used at checkout"
      ]
    },
    "reviews": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/products/{slug}/reviews"
    },
    "post_review": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/products/{slug}/reviews",
      "auth": "Bearer fmb_…",
      "notes": "Buyers only. stars 1-5. Optional text. Replies from the seller appear on GET."
    },
    "wishlist": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/wishlist",
      "auth": "Bearer fmb_…"
    },
    "notifications": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/notifications",
      "auth": "Bearer fmb_…"
    },
    "versions": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/listings/{id}/versions"
    },
    "search": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/search?q={query}",
      "notes": "Optional facets: type, tag, license, min_rating, seller, updated, works_with."
    },
    "seller_webhooks": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/me/webhooks",
      "auth": "Bearer fmk_…",
      "notes": "Recent deliveries and last failure. Host only. No signing secret."
    },
    "seller_listings": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/me/listings",
      "auth": "Bearer fmk_…",
      "notes": "Shop listings including hidden. Helper tokens allowed."
    },
    "seller_webhook_ping": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/me/webhooks/ping",
      "auth": "Bearer fmk_…",
      "notes": "Records a ping delivery. 200 delivered, 400 no endpoint, 502 failed, 429 isolate limit. Host only. No signing secret."
    },
    "openapi": {
      "method": "GET",
      "url": "https://filemarket.app/openapi.json"
    },
    "llms": {
      "method": "GET",
      "url": "https://filemarket.app/llms.txt"
    }
  },
  "seller_endpoints": {
    "auth": "Authorization: Bearer <seller token from /sell>. Scope: list, edit, read sales. Never payouts.",
    "me": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/me"
    },
    "sales": {
      "method": "GET",
      "url": "https://filemarket.app/api/v1/me/sales"
    },
    "upload": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/uploads",
      "headers": [
        "x-filename",
        "content-type",
        "x-kind: media (optional)"
      ],
      "notes": "zip, PDF, or a single file up to 100MB. Screenshots 4MB. Larger packs: POST /api/v1/uploads/init, PUT parts, POST complete."
    },
    "create_listing": {
      "method": "POST",
      "url": "https://filemarket.app/api/v1/listings"
    },
    "update_listing": {
      "method": "PATCH",
      "url": "https://filemarket.app/api/v1/listings/{id}"
    },
    "price_limits_cents": {
      "min": 50,
      "max": 149900
    }
  },
  "purchase_flow": [
    "GET /api/v1/catalog and choose a slug for the human.",
    "If they have no account: POST /api/v1/accounts/invite with email (never a password). The human gets a claim link by email when mail is wired. Unauthenticated callers always see the same generic message and never receive claim_url.",
    "GET /api/v1/wallet with the human's fmb_ token. Sleep buys need a funded Agentic Pay wallet.",
    "POST /api/v1/checkout with that token and slug. payment wallet returns download_url. 402 underfunded means ask the human to top up.",
    "If the wallet is empty and the human is present: POST without the token, hand them checkout_url, they pay on Stripe. Never enter card details.",
    "For a human Checkout, GET /api/v1/checkout/{session_id} with x-agent-id until paid."
  ],
  "webhooks": {
    "events": [
      "purchase.completed",
      "purchase.paid",
      "sale.paid",
      "refund.issued",
      "payout.paid",
      "version.published",
      "ticket.replied",
      "ping"
    ],
    "signature": "x-fm-signature: t=<unix>,v1=HMAC-SHA256(notify_secret, t + '.' + body)",
    "verify": "Reject if |now - t| > 300s or HMAC does not match. Same event id is a retry; treat as idempotent.",
    "note": "Account endpoint from /account. Empty notify_events means every event. Per-checkout notify_url still receives purchase.paid only. purchase.paid is an alias of purchase.completed."
  },
  "rate_limits": {
    "checkout": "20 per 15 minutes per IP, 60 per agent_id",
    "invite": "4 per hour per IP, 2 per day per email"
  },
  "contact": {
    "web": "https://filemarket.app/sell"
  }
}