{
  "openapi": "3.1.0",
  "info": {
    "title": "File Market Agent API",
    "version": "1.0.0",
    "description": "Catalog, checkout, and download. Open Stripe Checkout for the human. Sellers list with a Bearer token. Public endpoints need no key and are rate limited; every agent endpoint returns X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix seconds) and X-RateLimit-Policy, plus Retry-After on 429."
  },
  "servers": [
    {
      "url": "https://filemarket.app"
    }
  ],
  "components": {
    "securitySchemes": {
      "sellerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Seller API token fmk_… from /sell (scope: list, edit, read sales), or a helper token fmc_… (listings and versions only; other routes return 403)."
      },
      "buyerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Buyer token fmb_… from /account. Scope: library read, download grants, checkout status. Cannot buy or sell."
      }
    }
  },
  "webhooks": {
    "purchase.completed": {
      "post": {
        "summary": "Account endpoint: the buyer paid. Same payload as purchase.paid. Verify x-fm-signature (t=…,v1=HMAC-SHA256(notify_secret, t + '.' + body)); reject timestamps older than 300s. Retries reuse the delivery id.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "purchase.completed"
                    ]
                  },
                  "session_id": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "listing_id": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "price_cents": {
                    "type": "integer"
                  },
                  "currency": {
                    "type": "string"
                  },
                  "download_url": {
                    "type": "string"
                  },
                  "current_version": {
                    "type": "string"
                  },
                  "occurred_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "purchase.paid": {
      "post": {
        "summary": "Sent to a checkout notify_url or the buyer's account endpoint once the human pays. Alias of purchase.completed on the account endpoint. Verify x-fm-signature (t=…,v1=HMAC-SHA256(notify_secret, t + '.' + body)).",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "purchase.paid"
                    ]
                  },
                  "session_id": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "listing_id": {
                    "type": "string"
                  },
                  "title": {
                    "type": "string"
                  },
                  "price_cents": {
                    "type": "integer"
                  },
                  "currency": {
                    "type": "string"
                  },
                  "agent_id": {
                    "type": "string",
                    "nullable": true
                  },
                  "download_url": {
                    "type": "string"
                  },
                  "current_version": {
                    "type": "string"
                  },
                  "occurred_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "sale.paid": {
      "post": {
        "summary": "Sent to the seller account endpoint when an order is paid.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "sale.paid"
                    ]
                  },
                  "session_id": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "listing_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "refund.issued": {
      "post": {
        "summary": "Sent to buyer and seller account endpoints after File Market staff issues a refund. Sellers cannot self-serve this.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "refund.issued"
                    ]
                  },
                  "ticket_id": {
                    "type": "string"
                  },
                  "session_id": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer"
                  },
                  "via": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "payout.paid": {
      "post": {
        "summary": "Sent to the seller account endpoint when Stripe marks a Connect payout paid (payout.paid on the connected account).",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "payout.paid"
                    ]
                  },
                  "payout_id": {
                    "type": "string"
                  },
                  "amount_cents": {
                    "type": "integer"
                  },
                  "currency": {
                    "type": "string"
                  },
                  "arrival_date": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "version.published": {
      "post": {
        "summary": "Sent to each buyer's account endpoint when a purchased listing ships a new version.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "version.published"
                    ]
                  },
                  "listing_id": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "version": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    },
    "ticket.replied": {
      "post": {
        "summary": "Sent to the other party's account endpoint when a ticket gets a reply.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event": {
                    "type": "string",
                    "enum": [
                      "ticket.replied"
                    ]
                  },
                  "ticket_id": {
                    "type": "string"
                  },
                  "by": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "needs_info",
                      "resolved"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledged"
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/accounts/invite": {
      "post": {
        "operationId": "inviteAccount",
        "summary": "Start a pending account for a human (no password). Agent or public, rate limited per IP and email.",
        "description": "Creates or refreshes an unclaimed account for the email. Never send a password. Unauthenticated callers always receive the same generic message and never receive claim_url. A 48-hour claim link is emailed when mail is configured. claim_url is returned only to an authenticated seller or admin (seller token, or a signed-in seller/admin session with CSRF) when mail is off, or when ALLOW_DEV_GRANTS is true. Claimed emails get the same generic message. Until claim: checkouts may attach to the pending identity; no session, no seller powers, no fmb_/fmk_.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "handle": {
                    "type": "string",
                    "description": "Preferred File Market handle. Assigned if free; otherwise a nearby handle is used without saying so."
                  },
                  "display_name": {
                    "type": "string"
                  },
                  "displayName": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              },
              "examples": {
                "invite": {
                  "summary": "Invite a human",
                  "value": {
                    "email": "you@example.com",
                    "handle": "yourname",
                    "display_name": "You"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generic confirmation for every unauthenticated caller. claim_url is omitted unless the caller is an authenticated seller/admin (or ALLOW_DEV_GRANTS) and mail is off.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "claim_url": {
                      "type": "string",
                      "description": "Seller/admin or ALLOW_DEV_GRANTS only, and only when mail is off."
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "mailed": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "message": "If that inbox can join, a claim link was created."
                }
              }
            }
          },
          "400": {
            "description": "Invalid email, or a password field was sent"
          },
          "429": {
            "description": "Rate limited per IP or email"
          }
        }
      }
    },
    "/api/v1/catalog": {
      "get": {
        "operationId": "listCatalog",
        "summary": "List live products. Facets match Explore: type, tag, license, min_rating, seller, updated, works_with.",
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "bots",
                "agent",
                "software",
                "file"
              ]
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "license",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_rating",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                3,
                4
              ]
            }
          },
          {
            "name": "seller",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "official, independent, or a handle"
            }
          },
          {
            "name": "updated",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "week",
                "month"
              ]
            }
          },
          {
            "name": "works_with",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "products": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "capabilities": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "listing_type": {
                            "type": "string",
                            "enum": [
                              "agent",
                              "bots",
                              "file",
                              "software"
                            ],
                            "description": "Stored type is agent|file|software. Agent packs also expose type=bots. Filters accept bots, bot, agent, or agents."
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "bots",
                              "software",
                              "file"
                            ]
                          },
                          "category": {
                            "type": "string",
                            "nullable": true
                          },
                          "tags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "price_cents": {
                            "type": "integer"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "price_display": {
                            "type": "string"
                          },
                          "download_type": {
                            "type": "string",
                            "enum": [
                              "zip",
                              "pdf",
                              "json",
                              "binary"
                            ]
                          },
                          "payment": {
                            "type": "string",
                            "enum": [
                              "stripe_checkout",
                              "free_demo",
                              "free"
                            ]
                          },
                          "rating": {
                            "type": "object",
                            "properties": {
                              "average": {
                                "type": "number"
                              },
                              "count": {
                                "type": "integer"
                              }
                            }
                          },
                          "sales_count": {
                            "type": "integer"
                          },
                          "seller": {
                            "type": "object",
                            "properties": {
                              "handle": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "url": {
                                "type": "string"
                              }
                            }
                          },
                          "url": {
                            "type": "string"
                          },
                          "buy_url": {
                            "type": "string"
                          },
                          "agent_buy_url": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/products/{slug}": {
      "get": {
        "operationId": "getProduct",
        "summary": "Get one product",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "slug": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "capabilities": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "listing_type": {
                      "type": "string",
                      "enum": [
                        "agent",
                        "bots",
                        "file",
                        "software"
                      ],
                      "description": "Stored type is agent|file|software. Agent packs also expose type=bots. Filters accept bots, bot, agent, or agents."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "bots",
                        "software",
                        "file"
                      ]
                    },
                    "category": {
                      "type": "string",
                      "nullable": true
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price_cents": {
                      "type": "integer"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "price_display": {
                      "type": "string"
                    },
                    "download_type": {
                      "type": "string",
                      "enum": [
                        "zip",
                        "pdf",
                        "json",
                        "binary"
                      ]
                    },
                    "payment": {
                      "type": "string",
                      "enum": [
                        "stripe_checkout",
                        "free_demo",
                        "free"
                      ]
                    },
                    "rating": {
                      "type": "object",
                      "properties": {
                        "average": {
                          "type": "number"
                        },
                        "count": {
                          "type": "integer"
                        }
                      }
                    },
                    "sales_count": {
                      "type": "integer"
                    },
                    "seller": {
                      "type": "object",
                      "properties": {
                        "handle": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        }
                      }
                    },
                    "url": {
                      "type": "string"
                    },
                    "buy_url": {
                      "type": "string"
                    },
                    "agent_buy_url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown slug"
          }
        }
      }
    },
    "/api/v1/checkout": {
      "post": {
        "operationId": "createCheckout",
        "summary": "Pay from Agentic Pay with a buyer token, or create a Stripe Checkout for the human",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string",
                    "description": "Product slug. Omit when buying a bundle."
                  },
                  "bundle": {
                    "type": "string",
                    "description": "Collection slug with a bundle price. One Checkout for every listing in it."
                  },
                  "buyer_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "agent_id": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "success_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "https only. {CHECKOUT_SESSION_ID} is appended if missing."
                  },
                  "cancel_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "gift_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Buy as a gift: the recipient gets the pack in their library and an in-app note; the payer keeps the receipt."
                  },
                  "gift_message": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Optional note shown on the recipient's gift card."
                  },
                  "coupon": {
                    "type": "string",
                    "description": "Promo code. Invalid or inapplicable codes return 400 with the reason."
                  },
                  "ref": {
                    "type": "string",
                    "description": "Referrer handle to credit on a first purchase."
                  },
                  "notify_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "https endpoint that receives a signed purchase.paid event once the human pays."
                  },
                  "invite_token": {
                    "type": "string",
                    "description": "One-time account invite token. Attaches this checkout to the pending (unclaimed) identity only."
                  },
                  "pay": {
                    "type": "string",
                    "enum": [
                      "wallet",
                      "checkout"
                    ],
                    "description": "checkout forces Stripe. Default with an fmb_ token: debit Agentic Pay."
                  }
                }
              },
              "examples": {
                "onePaste": {
                  "summary": "One-paste agent checkout",
                  "description": "What the buyer setup prompt tells an agent to send. The agent hands checkout_url to the human and polls GET /api/v1/checkout/{session_id}.",
                  "value": {
                    "slug": "inbox-triage",
                    "buyer_email": "you@example.com",
                    "agent_id": "claude-desktop"
                  }
                },
                "withCoupon": {
                  "summary": "Coupon, referral, and webhook",
                  "value": {
                    "slug": "weekly-ops-brief",
                    "buyer_email": "you@example.com",
                    "agent_id": "ops-bot",
                    "coupon": "LAUNCH20",
                    "ref": "atelier",
                    "notify_url": "https://agent.example.com/hooks/file-market"
                  }
                },
                "bundle": {
                  "summary": "Bundle from a collection",
                  "value": {
                    "bundle": "starter-desk",
                    "buyer_email": "you@example.com",
                    "agent_id": "ops-bot"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout created",
            "content": {
              "application/json": {
                "example": {
                  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_a1B2c3",
                  "session_id": "cs_test_a1B2c3",
                  "status_url": "https://filemarket.app/api/v1/checkout/cs_test_a1B2c3",
                  "expires_at": "2026-09-07T13:00:00.000Z",
                  "human_next_step": "Open checkout_url and pay with Stripe; the agent polls status_url until status is paid."
                },
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkout_url": {
                      "type": "string"
                    },
                    "session_id": {
                      "type": "string"
                    },
                    "status_url": {
                      "type": "string"
                    },
                    "payment": {
                      "type": "string",
                      "enum": [
                        "wallet",
                        "stripe_checkout",
                        "free_demo",
                        "free"
                      ]
                    },
                    "download_url": {
                      "type": "string",
                      "nullable": true
                    },
                    "notify_secret": {
                      "type": "string",
                      "nullable": true,
                      "description": "Shared secret for verifying x-fm-signature on notify_url events. Shown once."
                    },
                    "product": {
                      "type": "object",
                      "properties": {
                        "slug": {
                          "type": "string"
                        },
                        "title": {
                          "type": "string"
                        },
                        "price_cents": {
                          "type": "integer"
                        },
                        "currency": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "402": {
            "description": "Agentic Pay underfunded, or daily agent spending cap reached"
          },
          "404": {
            "description": "Unknown slug"
          },
          "429": {
            "description": "Rate limited"
          },
          "503": {
            "description": "Payments unavailable"
          }
        }
      }
    },
    "/api/v1/sellers/{handle}": {
      "get": {
        "operationId": "getSeller",
        "summary": "Seller storefront: bio, listings, shelves, payout status, followers",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Seller"
          },
          "404": {
            "description": "Unknown handle"
          }
        }
      }
    },
    "/api/v1/collections": {
      "get": {
        "operationId": "listCollections",
        "summary": "Curated shelves and bundles with optional bundle_price_cents; buy a bundle with POST /api/v1/checkout { bundle: slug }",
        "responses": {
          "200": {
            "description": "Collections"
          }
        }
      },
      "post": {
        "operationId": "createCollection",
        "summary": "Create or update a shelf (seller token). Set bundle_price_cents below the sum of your one-time listings to sell them as a bundle in one Checkout.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "slug",
                  "listing_ids"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "listing_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "bundle_price_cents": {
                    "type": "integer"
                  }
                }
              },
              "example": {
                "title": "Ops Starter",
                "slug": "ops-starter",
                "description": "Both packs, one checkout",
                "listing_ids": [
                  "lst_a1",
                  "lst_b2"
                ],
                "bundle_price_cents": 4000
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created"
          }
        }
      }
    },
    "/api/v1/me/waitlists": {
      "get": {
        "operationId": "sellerWaitlists",
        "summary": "Waitlist counts per listing (seller token). People are alerted in-app on launch or restock; names are never exposed.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ count, listings[] }"
          }
        }
      }
    },
    "/embed/button.js": {
      "get": {
        "operationId": "embedButton",
        "summary": "Embeddable buy button script; add <script async src=…/embed/button.js data-listing=\"handle/slug\"></script> to any page. Opens Stripe Checkout through the public checkout API; no secrets involved.",
        "responses": {
          "200": {
            "description": "JavaScript"
          }
        }
      }
    },
    "/embed/card/{handle}/{slug}.svg": {
      "get": {
        "operationId": "embedCard",
        "summary": "Live badge with title and price for a listing; wrap it in a link to the listing page.",
        "parameters": [
          {
            "name": "handle",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SVG"
          }
        }
      }
    },
    "/api/v1/search": {
      "get": {
        "operationId": "search",
        "summary": "Grouped search: products, sellers, categories. Prefix @handle to scope to one shop. type=bots aliases agent. Facets: tag, license, min_rating, seller, updated, works_with.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "bots",
                "agent",
                "software",
                "file"
              ]
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "license",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "min_rating",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                3,
                4
              ]
            }
          },
          {
            "name": "seller",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "updated",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "week",
                "month"
              ]
            }
          },
          {
            "name": "works_with",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Groups"
          }
        }
      }
    },
    "/api/v1/me/webhooks": {
      "get": {
        "operationId": "sellerWebhookStatus",
        "summary": "Recent account webhook deliveries and last failure (seller token). Host only. Never returns the signing secret or a full notify URL.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ configured, endpoint_host, last_ok_at, last_failure_at, deliveries[] }"
          }
        }
      }
    },
    "/api/v1/me/listings": {
      "get": {
        "operationId": "sellerListListings",
        "summary": "List the shop's listings including hidden (seller token). Helper tokens allowed.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ handle, count, listings[] }"
          }
        }
      }
    },
    "/api/v1/me/webhooks/ping": {
      "post": {
        "operationId": "sellerWebhookPing",
        "summary": "Send a ping to the saved account webhook and record the delivery (seller token). Host only. Never returns the signing secret or a full notify URL.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Delivered"
          },
          "400": {
            "description": "No endpoint saved"
          },
          "429": {
            "description": "Isolate rate limit"
          },
          "502": {
            "description": "Endpoint failed"
          }
        }
      }
    },
    "/api/v1/products/{slug}/reviews": {
      "get": {
        "operationId": "listReviews",
        "summary": "Buyer reviews for a product, including seller replies",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Reviews with average and count"
          }
        }
      },
      "post": {
        "operationId": "postReview",
        "summary": "Rate a purchased listing (buyer token). One review per buyer; a second call replaces it.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "stars"
                ],
                "properties": {
                  "stars": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ review }"
          },
          "403": {
            "description": "Not a buyer"
          }
        }
      }
    },
    "/api/v1/products/{slug}/reviews/reply": {
      "post": {
        "operationId": "replyReview",
        "summary": "One public seller reply on a review (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id",
                  "text"
                ],
                "properties": {
                  "user_id": {
                    "type": "string"
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ review }"
          }
        }
      }
    },
    "/api/v1/wishlist": {
      "get": {
        "operationId": "listWishlist",
        "summary": "Saved listings (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ count, items[] }"
          }
        }
      },
      "post": {
        "operationId": "saveWishlist",
        "summary": "Save or remove a listing. Omit saved to toggle (buyer token).",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "listing_id": {
                    "type": "string"
                  },
                  "saved": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ saved, slug, listing_id, count }"
          }
        }
      }
    },
    "/api/v1/notifications": {
      "get": {
        "operationId": "listNotifications",
        "summary": "In-app notifications (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ unread, items[] }"
          }
        }
      }
    },
    "/api/v1/notifications/read": {
      "post": {
        "operationId": "markNotificationsRead",
        "summary": "Mark one notification or all of them read (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ unread, marked }"
          }
        }
      }
    },
    "/api/v1/collections/{slug}": {
      "get": {
        "operationId": "getCollection",
        "summary": "One shelf or bundle by slug, with current listing cards",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Collection"
          },
          "404": {
            "description": "Unknown slug"
          }
        }
      }
    },
    "/api/v1/listings/{id}/versions": {
      "get": {
        "operationId": "listVersions",
        "summary": "Published versions and changelogs",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Versions"
          }
        }
      },
      "post": {
        "operationId": "publishVersion",
        "summary": "Publish a new version (seller token). Safety checks run; quarantined versions are stored but not published. Send from_version instead of file_key to re-publish an existing pack with a new changelog.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "changelog"
                ],
                "properties": {
                  "file_key": {
                    "type": "string"
                  },
                  "from_version": {
                    "type": "string",
                    "description": "Existing version to duplicate, e.g. 1.0.0"
                  },
                  "changelog": {
                    "type": "string",
                    "maxLength": 600
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Published"
          },
          "202": {
            "description": "Held or quarantined; not published"
          }
        }
      }
    },
    "/api/v1/uploads": {
      "post": {
        "operationId": "upload",
        "summary": "Upload a pack (zip, PDF, or a single file, 100MB) or screenshot (seller token). Raw body; headers x-filename, content-type, optional x-kind: media (4MB). Oversized bodies return 413.",
        "description": "Packs up to 100MB. For files over a few megabytes prefer POST /api/v1/uploads/init then PUT 8MB parts. curl -X POST https://filemarket.app/api/v1/uploads -H 'authorization: Bearer fmk_…' -H 'content-type: application/zip' -H 'x-filename: inbox-triage-1.0.0.zip' --data-binary @inbox-triage.zip",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "201": {
            "description": "{ key, bytes }",
            "content": {
              "application/json": {
                "example": {
                  "key": "uploads/sel_a1b2c3d4/inbox-triage-1.0.0.zip",
                  "bytes": 48213,
                  "kind": "artifact"
                }
              }
            }
          },
          "413": {
            "description": "Packs must be 100MB or smaller."
          }
        }
      }
    },
    "/api/v1/uploads/init": {
      "post": {
        "operationId": "uploadInit",
        "summary": "Start a direct-to-R2 pack upload (seller token). Use for packs over a few megabytes, up to 100MB.",
        "description": "Send { filename, bytes, content_type? }. Then PUT /api/v1/uploads/{upload_id}/parts/{n} and POST /complete. Accepted delivery: zip, PDF, or a single file. Screenshots stay on POST /api/v1/uploads with x-kind: media.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename",
                  "bytes"
                ],
                "properties": {
                  "filename": {
                    "type": "string"
                  },
                  "bytes": {
                    "type": "integer",
                    "maximum": 104857600
                  },
                  "content_type": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ upload_id, file_key, part_size, parts_expected }"
          },
          "413": {
            "description": "Packs must be 100MB or smaller."
          }
        }
      }
    },
    "/api/v1/uploads/{upload_id}/parts/{n}": {
      "put": {
        "operationId": "uploadPart",
        "summary": "Upload one 8MB (or smaller last) part of a pack (seller token).",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "n",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ part, etag }"
          },
          "413": {
            "description": "Part or pack over the size cap."
          }
        }
      }
    },
    "/api/v1/uploads/{upload_id}/complete": {
      "post": {
        "operationId": "uploadComplete",
        "summary": "Finish a direct-to-R2 pack upload (seller token). Returns file_key for listings.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "upload_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "{ key, bytes }"
          }
        }
      }
    },
    "/api/v1/listings": {
      "post": {
        "operationId": "createListing",
        "summary": "Create a listing from an uploaded file_key (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "slug",
                  "type",
                  "price_cents",
                  "file_key"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "agent",
                      "bots",
                      "bot",
                      "software",
                      "file"
                    ],
                    "description": "bots and bot alias to agent."
                  },
                  "description": {
                    "type": "string"
                  },
                  "price_cents": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 149900,
                    "description": "USD cents. 0 is free (no Stripe). Paid listings are 50–149900."
                  },
                  "billing": {
                    "type": "string",
                    "enum": [
                      "once",
                      "monthly"
                    ],
                    "description": "monthly bills price_cents every month via Stripe Billing; buyers can cancel"
                  },
                  "file_key": {
                    "type": "string"
                  },
                  "media_keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "capabilities": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "license": {
                    "type": "string"
                  },
                  "changelog": {
                    "type": "string"
                  },
                  "unique": {
                    "type": "boolean"
                  },
                  "publish_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Schedule go-live instead of publishing now"
                  },
                  "request_feature": {
                    "type": "boolean",
                    "description": "Ask an admin to feature the listing on the homepage. Admins decide; the flag never sets featured by itself."
                  },
                  "price_test_cents": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Seller-only A/B price test: an alternate one-time price shown to half of web visitors; null ends it. Agents and this API always see price_cents."
                  }
                }
              },
              "examples": {
                "onePastePublish": {
                  "summary": "One-paste seller publish",
                  "description": "Step 3 of the seller setup prompt: upload first, then create the listing from the returned file_key.",
                  "value": {
                    "title": "Inbox Triage",
                    "slug": "inbox-triage",
                    "type": "agent",
                    "description": "Sorts a mailbox into Now, Later, Waiting, and Ignore, then drafts three replies. Ships SYSTEM.md, examples, and an eval set.",
                    "price_cents": 1900,
                    "file_key": "uploads/sel_a1b2c3d4/inbox-triage-1.0.0.zip",
                    "media_keys": [
                      "media/sel_a1b2c3d4/cover.png"
                    ],
                    "capabilities": [
                      "email triage",
                      "reply drafting"
                    ],
                    "tags": [
                      "ops",
                      "email",
                      "agents"
                    ],
                    "license": "Per buyer, updates included, no resale.",
                    "changelog": "Initial release",
                    "video_url": "https://youtu.be/dQw4w9WgXcQ"
                  }
                },
                "monthly": {
                  "summary": "Monthly pack",
                  "value": {
                    "title": "Weekly Ops Brief",
                    "slug": "weekly-ops-brief",
                    "type": "file",
                    "description": "A Friday brief on ops tooling and workflows, delivered as a fresh version every week.",
                    "price_cents": 900,
                    "billing": "monthly",
                    "file_key": "uploads/sel_a1b2c3d4/ops-brief-2026-36.pdf"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Published",
            "content": {
              "application/json": {
                "example": {
                  "listing": {
                    "id": "lst_9f8e7d6c5b4a",
                    "slug": "inbox-triage",
                    "url": "https://filemarket.app/s/atelier/inbox-triage",
                    "price_cents": 1900,
                    "active": true
                  },
                  "qa": {
                    "publishable": true,
                    "blocking": [],
                    "warnings": []
                  }
                }
              }
            }
          },
          "202": {
            "description": "Created but held by safety checks or the publish checklist",
            "content": {
              "application/json": {
                "example": {
                  "listing": {
                    "id": "lst_9f8e7d6c5b4a",
                    "slug": "inbox-triage",
                    "active": false
                  },
                  "qa": {
                    "publishable": false,
                    "blocking": [
                      {
                        "id": "description",
                        "label": "Description says what the buyer gets (40+ characters)"
                      }
                    ],
                    "warnings": []
                  },
                  "next_step": "PATCH /api/v1/listings/lst_9f8e7d6c5b4a with a longer description, then set active:true."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/listings/{id}": {
      "get": {
        "operationId": "getListing",
        "summary": "Listing by id",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Product"
          }
        }
      },
      "delete": {
        "operationId": "deleteListing",
        "summary": "Move a listing to trash (seller token). Restorable for 30 days; buyers keep downloads.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ listing, deleted_at, restore_until }"
          }
        }
      },
      "patch": {
        "operationId": "updateListing",
        "summary": "Edit metadata (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "price_cents": {
                    "type": "integer"
                  },
                  "capabilities": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "media_keys": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "video_url": {
                    "type": "string",
                    "nullable": true,
                    "description": "YouTube or Loom URL; stored canonical, shown as a thumbnail that opens in a new tab. Other hosts are rejected (400)."
                  },
                  "works_with": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Agent ids you tested with (claude, chatgpt, gemini, grok, cursor, perplexity, ...). Empty means any agent. Drives the Works-with filter on Explore."
                  },
                  "og_media_index": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Index into media_keys featured first in JSON-LD. Social share cards are generated from title and handle, not this screenshot."
                  },
                  "delivery_notes": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 4000,
                    "description": "After-you-buy markdown shown to buyers on the receipt, in the library, and in library JSON. Never public. Same text for every buyer, so no one-time secrets."
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "license": {
                    "type": "string"
                  },
                  "unique": {
                    "type": "boolean"
                  },
                  "billing": {
                    "type": "string",
                    "enum": [
                      "once",
                      "monthly"
                    ]
                  },
                  "publish_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true,
                    "description": "Schedule go-live (future, within 90 days). Listing hides until then and activates automatically; null clears."
                  },
                  "max_sales": {
                    "type": "integer",
                    "nullable": true
                  },
                  "max_active_subscriptions": {
                    "type": "integer",
                    "nullable": true
                  },
                  "faq": {
                    "type": "array",
                    "nullable": true,
                    "maxItems": 8,
                    "items": {
                      "type": "object",
                      "properties": {
                        "q": {
                          "type": "string",
                          "maxLength": 120
                        },
                        "a": {
                          "type": "string",
                          "maxLength": 600
                        }
                      }
                    }
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "coming_soon": {
                    "type": "boolean",
                    "description": "Hide Buy, show on the storefront with a notify-me list. Setting active:true later notifies everyone waiting."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated"
          }
        }
      }
    },
    "/api/v1/library": {
      "get": {
        "operationId": "buyerLibrary",
        "summary": "The human's purchases with versions, entitlement keys, seats, subscription status with a manage_url the human can open to change or cancel billing, the seller's after-you-buy delivery_notes, refunded_at, and download endpoints (buyer token). ?format=csv for a spreadsheet.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Library"
          }
        }
      }
    },
    "/api/v1/library/{session_id}/seats": {
      "get": {
        "operationId": "listSeats",
        "summary": "Household seats on a purchase (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ seats[], max }"
          }
        }
      },
      "post": {
        "operationId": "inviteSeat",
        "summary": "Invite an email to share this purchase (max 3, no charge). Returns invite_url to give them.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ seat, invite_url, expires_in }"
          },
          "409": {
            "description": "Seat limit or duplicate"
          }
        }
      }
    },
    "/api/v1/library/{session_id}/seats/{seat_id}": {
      "delete": {
        "operationId": "revokeSeat",
        "summary": "Revoke a seat; their library copy disappears (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seat_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked"
          }
        }
      }
    },
    "/api/v1/library/{slug}/download": {
      "get": {
        "operationId": "buyerDownload",
        "summary": "Fresh short-lived download link for a purchased slug (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ download_url, expires_in, entitlement_key }"
          },
          "404": {
            "description": "Not purchased"
          }
        }
      }
    },
    "/api/v1/entitlements/verify": {
      "get": {
        "operationId": "verifyEntitlement",
        "summary": "Verify a purchase entitlement key. Public, no personal data.",
        "parameters": [
          {
            "name": "key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^FM-[A-Z2-9]{4}-[A-Z2-9]{4}-[A-Z2-9]{4}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ valid, slug, seller, issued_at, current_version }"
          }
        }
      }
    },
    "/feeds/versions.xml": {
      "get": {
        "operationId": "siteFeed",
        "summary": "Atom feed of new versions across the market. Per-listing: /s/{handle}/{slug}/feed.xml",
        "responses": {
          "200": {
            "description": "Atom"
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "operationId": "sellerMe",
        "summary": "Seller profile, listings, payout status, limits (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Seller"
          }
        }
      }
    },
    "/api/v1/me/sales": {
      "get": {
        "operationId": "sellerSales",
        "summary": "Confirmed Stripe orders (seller token). ?format=csv for a spreadsheet.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Orders"
          }
        }
      }
    },
    "/api/v1/me/setup": {
      "get": {
        "operationId": "sellerSetup",
        "summary": "Structured seller checklist: payouts status, listings, limits, next_step (seller token). Call this first.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ has_seller, connect{status,url}, token_ok, listings{}, next_step }"
          }
        }
      }
    },
    "/api/v1/me/connect-link": {
      "post": {
        "operationId": "sellerConnectLink",
        "summary": "Fresh Stripe hosted onboarding link for payouts (seller token). Give the url to the human; Stripe collects identity and bank details.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "201": {
            "description": "{ url, expires_in, status }"
          },
          "409": {
            "description": "Payouts already active"
          }
        }
      }
    },
    "/api/v1/wallet": {
      "get": {
        "operationId": "getWallet",
        "summary": "Agentic Pay balance and ledger (buyer token). Agents debit. Nobody withdraws.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ balance_cents, withdraw: false, topup_url, entries[] }"
          }
        }
      }
    },
    "/api/v1/wallet/topup": {
      "post": {
        "operationId": "walletTopup",
        "summary": "Stripe Checkout so the human can fund Agentic Pay (buyer token). Cards stay in Stripe.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount_cents"
                ],
                "properties": {
                  "amount_cents": {
                    "type": "integer",
                    "minimum": 500,
                    "maximum": 50000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ checkout_url, amount_cents }"
          },
          "503": {
            "description": "Payments off; human_url is /account#wallet"
          }
        }
      }
    },
    "/api/v1/tickets": {
      "get": {
        "operationId": "buyerTickets",
        "summary": "Tickets the human opened (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ count, tickets[] }"
          }
        }
      },
      "post": {
        "operationId": "openTicket",
        "summary": "Open a support ticket (buyer token). Refund needs session_id from a purchase on this account.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "message"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "refund",
                      "download",
                      "report",
                      "other"
                    ]
                  },
                  "message": {
                    "type": "string",
                    "minLength": 10,
                    "maxLength": 2000
                  },
                  "session_id": {
                    "type": "string"
                  },
                  "sku": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ ticket }"
          }
        }
      }
    },
    "/api/v1/tickets/{id}/reply": {
      "post": {
        "operationId": "replyAsBuyer",
        "summary": "Reply on a ticket the human opened (buyer token)",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "maxLength": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ ticket }"
          }
        }
      }
    },
    "/api/v1/tickets/{id}/attach": {
      "post": {
        "operationId": "attachBuyerEvidence",
        "summary": "Attach a PNG, JPEG, WebP, or GIF (base64, 2MB) to a ticket the human opened. Max 8 images.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content_base64"
                ],
                "properties": {
                  "filename": {
                    "type": "string"
                  },
                  "content_base64": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ ticket }"
          }
        }
      }
    },
    "/api/v1/library/setup": {
      "get": {
        "operationId": "buyerSetup",
        "summary": "Buyer checklist (buyer token): library counts, wallet, spending cap, scopes, next_step. Call first.",
        "security": [
          {
            "buyerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Setup"
          }
        }
      }
    },
    "/api/v1/listings/{id}/restore": {
      "post": {
        "operationId": "restoreListing",
        "summary": "Restore a trashed listing as hidden within 30 days (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Restored"
          },
          "410": {
            "description": "Restore window closed"
          }
        }
      }
    },
    "/api/v1/listings/{id}/clone": {
      "post": {
        "operationId": "cloneListing",
        "summary": "Duplicate a listing into a hidden draft (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Draft listing"
          }
        }
      }
    },
    "/api/v1/listings/bulk": {
      "post": {
        "operationId": "bulkVisibility",
        "summary": "Hide or show up to 50 listings (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids",
                  "active"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ updated[] }"
          }
        }
      }
    },
    "/api/v1/leaders": {
      "get": {
        "operationId": "leaders",
        "summary": "Top sellers by USD volume with rank movement",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "30d",
                "7d"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ window, rows[] { handle, sales, volume_cents, movement } }"
          }
        }
      }
    },
    "/api/v1/me/tickets": {
      "get": {
        "operationId": "sellerTickets",
        "summary": "Support tickets on the seller's listings with replies (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "{ count, tickets[] }"
          }
        }
      }
    },
    "/api/v1/me/tickets/{id}/reply": {
      "post": {
        "operationId": "replyTicket",
        "summary": "Reply to a ticket as the seller; marks answered unless status given (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "answered",
                      "closed"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ ticket }"
          }
        }
      }
    },
    "/api/v1/me/tickets/{id}/attach": {
      "post": {
        "operationId": "attachSellerEvidence",
        "summary": "Attach a PNG, JPEG, WebP, or GIF (base64, 2MB) to a ticket on the seller's listings. Max 8 images.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "content_base64"
                ],
                "properties": {
                  "filename": {
                    "type": "string"
                  },
                  "content_base64": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "{ ticket }"
          }
        }
      }
    },
    "/api/v1/me/weekly": {
      "get": {
        "operationId": "sellerWeekly",
        "summary": "Last 7 days vs prior 7: orders, revenue, followers, tickets, versions, tips (seller token). ?format=csv for a spreadsheet.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Weekly summary"
          }
        }
      }
    },
    "/api/v1/me/pin": {
      "post": {
        "operationId": "pinListing",
        "summary": "Pin one listing to the top of the storefront, or null to unpin (seller token)",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "listing_id": {
                    "type": "string",
                    "nullable": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "{ pinned_listing_id }"
          }
        }
      }
    },
    "/api/v1/me/announcements": {
      "post": {
        "operationId": "sellerAnnounce",
        "summary": "Post a storefront update (seller token). Followers get an in-app notification.",
        "security": [
          {
            "sellerToken": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 500
                  },
                  "link": {
                    "type": "string",
                    "description": "https URL or a File Market path"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Announcement"
          }
        }
      }
    },
    "/status.json": {
      "get": {
        "operationId": "status",
        "summary": "Public health of Worker, storage, payments, auth, catalog, uploads, downloads, and Agentic Pay. No secrets.",
        "responses": {
          "200": {
            "description": "{ status, checked_at, probes[] }"
          },
          "503": {
            "description": "Something is down"
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "mcp",
        "summary": "Remote MCP server (JSON-RPC 2.0). Methods: initialize, tools/list, tools/call.",
        "responses": {
          "200": {
            "description": "JSON-RPC response"
          }
        }
      }
    },
    "/api/v1/checkout/{session_id}": {
      "get": {
        "operationId": "getCheckoutStatus",
        "summary": "Payment status and download link once paid",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "paid",
                        "expired",
                        "unpaid"
                      ]
                    },
                    "slug": {
                      "type": "string",
                      "nullable": true
                    },
                    "download_url": {
                      "type": "string",
                      "nullable": true
                    },
                    "download_urls": {
                      "type": "array",
                      "nullable": true,
                      "items": {
                        "type": "object",
                        "properties": {
                          "slug": {
                            "type": "string"
                          },
                          "download_url": {
                            "type": "string"
                          }
                        }
                      },
                      "description": "Present for bundles"
                    },
                    "bundle": {
                      "type": "string",
                      "nullable": true
                    },
                    "checkout_url": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "x-agent-id does not match the agent_id that opened the checkout (a buyer token for the paying account also works)"
          },
          "404": {
            "description": "Not a File Market session"
          }
        }
      }
    }
  }
}