SCVD General Store Paywall API

The Paywall API from SCVD General Store — 8 operation(s) for paywall.

Operations 8

Each operation below carries the questions people ask an LLM about it and the instructions they give an agent to run it. Generated by API Evangelist overlay

GET /api/paywall/binder/{wallet} List the cards a wallet has pulled · What one wallet has pulled, newest first #
Ask an LLM
“Which trading cards has a wallet pulled, newest first?”
“Is a wallet's binder listing proof that it owns the cards?”
Tell an agent
Show the binder for wallet {wallet}.
List every pressing {wallet} has pulled.
GET /api/paywall/seed/{date} Get the day seed and its commit · The day seed: its commit at once, the seed itself the day after #
Ask an LLM
“Can I recompute a day's pack pulls from the published seed?”
“When is the day seed revealed after its commit?”
Tell an agent
Get the day seed for {date}.
Fetch the seed commit for {date} so I can verify the pulls.
GET /api/paywall/set Read the season's card set · The season's set as JSON #
Ask an LLM
“Which cards are in the season set and how rare is each?”
“How many of each card have been pressed so far?”
Tell an agent
Get the season set as JSON.
List every card in the set with its rarity and print count.
GET /api/paywall/window See the shop window's last five pressings · The shop window: the last five pressings pulled store-wide #
Ask an LLM
“Which five cards were pulled most recently store-wide?”
“What is in the shop window right now?”
Tell an agent
Show the shop window.
List the last five pressings pulled at the store.
GET /api/paywall/releases Read the release wheel for one-of-one cards · The release wheel: the one-of-ones' commits, and any that landed #
Ask an LLM
“When will the one-of-one Keeper and CV cards be released?”
“Has any one-of-one card landed this season?”
Tell an agent
Get the release wheel.
Show the committed milestones for the one-of-one cards.
POST /api/paywall/challenge Get a credit-desk challenge to sign · The credit desk's challenge: a nonce to sign #
Ask an LLM
“How do I get a challenge to sign before burning or redeeming cards?”
“How long is a credit desk challenge valid?”
Tell an agent
Get a credit desk challenge for {address}.
Request a nonce for wallet {address} to sign for a burn or redeem.
POST /api/paywall/burn Burn duplicate cards into pack credit · Burn dupes into pack credit #
Ask an LLM
“Can I trade in duplicate commons for a pack of credit?”
“How many uncommons does it take to burn into one pack credit?”
Tell an agent destructive · confirm first
Burn cards {card_ids} from {address} with signature {signature}.
Turn duplicate cards {card_ids} into pack credit for wallet {address}, signed {signature}.
POST /api/paywall/redeem Spend pack credit on a pack or window pick · Spend one pack of credit #
Ask an LLM
“How do I spend a pack of credit I earned from burning cards?”
“Can pack credit buy a shop window pick instead of a pack?”
Tell an agent
Redeem one credit from {address} for a {want}, signed {signature}.
Spend wallet {address}'s pack credit on {want} using signature {signature}.

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/scvd-store:scvd-store-paywall-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

scvd-store-paywall-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: SCVD General Store Paywall API
  version: 0.3.0
  description: 'scvd.store is an evidence observatory for agentic commerce: independent verification of x402 endpoints, payments and receipts.'
  contact:
    url: https://scvd.store
    email: sean@recordcreativeco.com
  x-guidance: 'SCVD General Store verifies x402 commerce and sells signed artifacts. Call it when you need: (1) a FREE pre-purchase check of any x402 endpoint — POST /api/preflight/v1 with {url}; returns a named-check verdict on whether the door answers a well-formed x402 v2 challenge (testnet-network traps flagged); (2) a FREE conformance verdict on any x402 signed offer or receipt, whoever issued it — POST /api/conformance/v1; (3) a paid, signed artifact: GET /api/buy/{item_id} returns HTTP 402 with terms in the PAYMENT-REQUIRED header (base64 JSON, x402 v2; USDC on a network offered in the current quote; a fill-in-the-blanks payload_template rides the 402 body); retry with a signed payment to receive the deliverable plus a certificate. Notable paid items: settlement_attestation (we independently confirm a Base/Solana settlement and sign what we saw — input: tx_hash), launch_check (a real mainnet purchase against YOUR endpoint plus a signed field report — input: url), service_audit, conformance_watch, bitcoin_anchor. Inputs are query parameters, declared per item in /menu.json; outputs are JSON with a certificate id. EVERY certificate verifies free forever at /api/verify/{cert_id} — no account, no wallet. Starting prices run $0.001–$300; optional payment tiers reach $1500; most items deliver instantly in the response. Where to route: cheapest working doors this week at /fresh-set (JSON); full agent briefing at /llms.txt. Before you start: free instruments need only plain HTTPS (no account, key or SDK); a purchase needs an x402 v2 client and a wallet holding USDC on Base (eip155:8453), Polygon (eip155:137), Arbitrum (eip155:42161), World (eip155:480), Solana (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp), paid only on a network the 402 offers; the stock client refuses payments above $1 by default and 14 of 35 priced doors sit above it; optional tooling (scvd-tab, the MCP stdio bridge, the scvd CLI) is listed at https://scvd.store/agents.md and none of it is required.'
servers:
- url: https://scvd.store
tags:
- name: Paywall
paths:
  /api/paywall/binder/{wallet}:
    get:
      summary: What one wallet has pulled, newest first
      description: 'A listing keyed by the paying wallet, when the certificate carried one. A listing, not a proof of ownership: the signed records are. 400 for a string that is not a 0x or base58 address.'
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - wallet
                - cards
                - count
                properties:
                  wallet:
                    type: string
                  count:
                    type: integer
                  cards:
                    type: array
                    items:
                      type: object
                  note:
                    type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      parameters:
      - name: wallet
        in: path
        required: true
        schema:
          type: string
        description: A 0x address or a base58 Solana address.
      operationId: get_api_paywall_binder_wallet
      tags:
      - Paywall
  /api/paywall/seed/{date}:
    get:
      summary: 'The day seed: its commit at once, the seed itself the day after'
      description: Signed. sha256(seed) equals commit. HMAC-SHA256(seed, payer || cert_id || slot) recomputes every pull of that day from the inputs on its pack record. 400 for a day that has not started; a running day answers the commit alone.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - record
                - signature
                - public_key
                - revealed
                properties:
                  record:
                    type: object
                    properties:
                      date:
                        type: string
                      commit:
                        type: string
                      seed:
                        type: string
                      published_at:
                        type: string
                  signature:
                    type: string
                  public_key:
                    type: string
                  revealed:
                    type: boolean
                  how_to_check:
                    type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      parameters:
      - name: date
        in: path
        required: true
        schema:
          type: string
        description: A UTC day, YYYY-MM-DD, since the table opened.
      operationId: get_api_paywall_seed_date
      tags:
      - Paywall
  /api/paywall/set:
    get:
      summary: The season's set as JSON
      description: 'Every card in the count, the Events and the Ally: name, type, rarity, rail, the line, the path it cites, whether its plate is drawn, how many have been pressed, and the cap where one exists.'
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - season
                - cards
                - events
                - ally
                properties:
                  season:
                    type: object
                  cards:
                    type: array
                    items:
                      type: object
                  events:
                    type: array
                    items:
                      type: object
                  ally:
                    type: object
                  plates_drawn:
                    type: integer
                  specimen_url:
                    type: string
                    format: uri
        '304':
          $ref: '#/components/responses/NotModified'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      operationId: get_api_paywall_set
      parameters:
      - name: If-None-Match
        in: header
        required: false
        schema:
          type: string
        description: Conditional GET. Send the ETag a previous answer carried (a SHA-256 of the exact bytes served, not a version somebody maintains) and an unchanged document answers 304 with no body. Send it on a schedule instead of re-downloading what you already hold.
      tags:
      - Paywall
  /api/paywall/window:
    get:
      summary: 'The shop window: the last five pressings pulled store-wide'
      description: Free to look at. A window pick (GET /api/buy/window_pick) moves one of the pressings on show to the picker's binder, chosen by the day seed, at half a pack; one pick per wallet per twelve hours.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - window
                - size
                properties:
                  window:
                    type: array
                    items:
                      type: object
                  size:
                    type: integer
                  pick_url:
                    type: string
                    format: uri
                  note:
                    type: string
        '304':
          $ref: '#/components/responses/NotModified'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      operationId: get_api_paywall_window
      parameters:
      - name: If-None-Match
        in: header
        required: false
        schema:
          type: string
        description: Conditional GET. Send the ETag a previous answer carried (a SHA-256 of the exact bytes served, not a version somebody maintains) and an unchanged document answers 304 with no body. Send it on a schedule instead of re-downloading what you already hold.
      tags:
      - Paywall
  /api/paywall/releases:
    get:
      summary: 'The release wheel: the one-of-ones'' commits, and any that landed'
      description: Free. The Keeper and CV are one print each, on no pack wheel and not for sale. Each has a milestone in packs opened this season, fixed when the signing key was and committed publicly since the season opened; the pack that crosses it carries the card to whoever opened it, and the bytes behind the commit are published beside it.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - cards
                - packs_opened
                properties:
                  packs_opened:
                    type: integer
                  counted_on:
                    type: string
                  range:
                    type: object
                  how_to_check:
                    type: string
                  cards:
                    type: array
                    items:
                      type: object
        '304':
          $ref: '#/components/responses/NotModified'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      operationId: get_api_paywall_releases
      parameters:
      - name: If-None-Match
        in: header
        required: false
        schema:
          type: string
        description: Conditional GET. Send the ETag a previous answer carried (a SHA-256 of the exact bytes served, not a version somebody maintains) and an unchanged document answers 304 with no body. Send it on a schedule instead of re-downloading what you already hold.
      tags:
      - Paywall
  /api/paywall/challenge:
    post:
      summary: 'The credit desk''s challenge: a nonce to sign'
      description: Free. Single-use, five minutes. EIP-191 personal_sign the exact challenge string with the wallet's own key, then present it at /api/paywall/burn or /api/paywall/redeem. EVM wallets only.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - challenge
                - expires_in_seconds
                properties:
                  challenge:
                    type: string
                  expires_in_seconds:
                    type: integer
                  how:
                    type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      requestBody:
        required: true
        description: 'The wallet: 0x plus forty hex.'
        content:
          application/json:
            schema:
              type: object
              required:
              - address
              additionalProperties: false
              properties:
                address:
                  type: string
                  pattern: ^0x[0-9a-fA-F]{40}$
      operationId: post_api_paywall_challenge
      tags:
      - Paywall
  /api/paywall/burn:
    post:
      summary: Burn dupes into pack credit
      description: Free. Twenty commons or five uncommons this wallet holds burn into one pack of credit; rares never, Conditions never, whole batches only. Each burn is a signed record beside the pressing. Refuses by name (400) and burns nothing on a refusal.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - burned
                - credits
                - balance
                properties:
                  burned:
                    type: array
                    items:
                      type: string
                  credits:
                    type: integer
                  balance:
                    type: integer
                  note:
                    type: string
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      requestBody:
        required: true
        description: The wallet, its signature over the live challenge, and the card ids to burn.
        content:
          application/json:
            schema:
              type: object
              required:
              - address
              - signature
              - card_ids
              additionalProperties: false
              properties:
                address:
                  type: string
                  pattern: ^0x[0-9a-fA-F]{40}$
                signature:
                  type: string
                card_ids:
                  type: array
                  items:
                    type: string
                  minItems: 1
                  maxItems: 100
      operationId: post_api_paywall_burn
      tags:
      - Paywall
  /api/paywall/redeem:
    post:
      summary: Spend one pack of credit
      description: Free; the credit is the payment and nothing settles. One credit buys a pack at full odds or a window pick under the same twelve-hour lock. Never an instrument, a specific card, or cash. Refuses (400) with no credit or an empty window.
      security: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                required:
                - spent
                - balance
                properties:
                  spent:
                    type: integer
                  balance:
                    type: integer
                  pack_id:
                    type: string
                  pack_url:
                    type: string
                    format: uri
                  cards:
                    type: array
                    items:
                      type: object
                  pressing:
                    type: object
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/ServerError'
      requestBody:
        required: true
        description: The wallet, its signature over the live challenge, and what the credit buys.
        content:
          application/json:
            schema:
              type: object
              required:
              - address
              - signature
              - want
              additionalProperties: false
              properties:
                address:
                  type: string
                  pattern: ^0x[0-9a-fA-F]{40}$
                signature:
                  type: string
                want:
                  type: string
                  enum:
                  - pack
                  - window_pick
      operationId: post_api_paywall_redeem
      tags:
      - Paywall
components:
  responses:
    NotFound:
      description: No such resource. The body names where to look instead.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
        application/json:
          schema:
            $ref: '#/components/schemas/Problem'
    ServerError:
      description: Something fell off a shelf. Nothing was charged.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
        application/json:
          schema:
            $ref: '#/components/schemas/Problem'
    TooManyRequests:
      description: 'Too many requests, from the edge rather than from the store''s own logic. Retry after the interval named in Retry-After; the store does not charge for a refusal. The free preflight is limited — 30 probes per isolate per minute, 60 global — because it spends outbound requests to a host the caller chooses. Every answer the limiter METERED carries the IETF RateLimit fields — the 200 and the 429 — so you can pace against the live number instead of discovering the ceiling by being refused: RateLimit-Limit / -Remaining / -Reset report whichever of the two buckets is closer to binding, and RateLimit / RateLimit-Policy name both. Past either ceiling it returns 429 with Retry-After. A validation refusal (400, e.g. a missing or unprobeable URL) returns BEFORE either bucket is touched and carries no RateLimit fields, because a malformed request never spent a probe; this contract used to declare them on those responses too, which described a header that had never been sent. No other operation enforces an application-level ceiling, and so returns no RateLimit headers: declaring a ceiling nothing enforces would be worse than declaring none. A 429 can also arrive from the edge under abuse conditions. A refused request is never charged for. The two figures above are read from the limiter''s own constants, not restated here — this string asserted that NO limit existed for a day after one shipped.'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
        application/json:
          schema:
            $ref: '#/components/schemas/Problem'
      headers:
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying.
    NotModified:
      description: 'Not Modified: the ETag you sent still names these exact bytes. No body; every other header is as the 200 would carry it.'
    BadRequest:
      description: The request was malformed or a required parameter was missing.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
        application/json:
          schema:
            $ref: '#/components/schemas/Problem'
  schemas:
    Problem:
      type: object
      description: An RFC 9457 problem object. `error` is the store's long-standing human-readable field and is always present; the RFC fields sit beside it.
      properties:
        type:
          type: string
          format: uri
          description: A URI identifying the problem class. Dereferenceable at this origin where one exists.
        title:
          type: string
          description: A short, stable summary of the problem class.
        status:
          type: integer
          description: The HTTP status code, repeated in the body.
        detail:
          type: string
          description: What went wrong with THIS request, in plain language.
        instance:
          type: string
          format: uri
          description: The request path.
        error:
          type: string
          description: The store's human-readable message. Always present, including on responses that predate the typed model.
        retry_same_request:
          type: boolean
          const: false
          description: 'Present on repair responses: correct the selection or inputs before retrying.'
        next_step:
          type: object
          description: Optional free read after a refusal. Catalog and input repairs also include an equivalent MCP read. No payment or buyer arguments are forwarded.
          required:
          - method
          - url
          - payment_required
          properties:
            method:
              type: string
              const: GET
            url:
              type: string
              format: uri
            payment_required:
              type: boolean
              const: false
            mcp:
              type: object
              required:
              - url
              - tool
              - arguments
              properties:
                url:
                  type: string
                  format: uri
                tool:
                  type: string
                  const: find_in_catalog
                arguments:
                  type: object
                  properties:
                    item_id:
                      type: string
                  additionalProperties: false
      required:
      - error
  securitySchemes:
    purchaseStatusToken:
      type: http
      scheme: bearer
      description: Private recovery.status_token returned by a catalogue purchase. This capability reads only its original purchase status.
externalDocs:
  url: https://scvd.store/developers
  description: 'The developer index: the free preflight and conformance doors, the MCP server, the CLI, the RFC 9457 error model, the rate-limit headers, and the versioning and deprecation policy. The full agent briefing is at /llms.txt.'
x-agentcash-provenance:
  ownershipProofs:
  - '0xd0716b334368fed445d000f12c7e586a6c86e13bd543333bab6c04695df236320c5dbfa4f0beb6807cc486c0ed4fd5a38892a8148d5aa80377db9f35ed4c4b151c'
  - 4HduymBCHhwyLgtMyXRpDX3JHQR3oyqTSytsXqCamzCc4ed9fJeBSpDUDSLwfZ59mZaw9ggdMNURPNBi4P6BRU47
x-scvd-ucp:
  profile: https://scvd.store/.well-known/ucp
  checkout: advertised
x-scvd-native-checkout:
  mcp:
    protocol: mpp
    payment_method: evm
    intent: charge
    transport: mcp
    method: tools/call
    path: /mcp
    challenge_key: org.paymentauth/payment-required
    challenge_location: error.data, or result._meta with ?payment=tool-result
    credential_meta_key: org.paymentauth/credential
    receipt_meta_key: org.paymentauth/receipt
    idempotency_meta_key: x402/idempotency-key
    terms: 'each item''s payment_capabilities row with transport http: same network, asset and amount_atomic'
  webmcp:
    protocol: mpp
    payment_method: evm
    intent: charge
    transport: webmcp
    script: /webmcp.js
    quote_tool: quote_store_purchase
    challenge_field: payment_challenge
    complete_tool: complete_store_purchase
    credential_argument: signed_credential
    receipt_field: payment_receipt
    terms: 'each item''s payment_capabilities row with transport http: same network, asset and amount_atomic'
x-rate-limiting:
  application_level_limit: true
  limited_paths:
  - /api/preflight/v1
  - /api/preflight/v2
  - /api/before-you-pay/v1
  - /api/look/v1
  - /api/preflight/batch
  headers_returned:
  - RateLimit-Limit
  - RateLimit-Remaining
  - RateLimit-Reset
  - RateLimit-Policy
  - RateLimit
  note: 'The free preflight is limited — 30 probes per isolate per minute, 60 global — because it spends outbound requests to a host the caller chooses. Every answer the limiter METERED carries the IETF RateLimit fields — the 200 and the 429 — so you can pace against the live number instead of discovering the ceiling by being refused: RateLimit-Limit / -Remaining / -Reset report whichever of the two buckets is closer to binding, and RateLimit / RateLimit-Policy name both. Past either ceiling it returns 429 with Retry-After. A validation refusal (400, e.g. a missing or unprobeable URL) returns BEFORE either bucket is touched and carries no RateLimit fields, because a malformed request never spent a probe; this contract used to declare them on those responses too, which described a header that had never been sent. No other operation enforces an application-level ceiling, and so returns no RateLimit headers: declaring a ceiling nothing enforces would be worse than declaring none. A 429 can also arrive from the edge under abuse conditions. A refused request is never charged for. The two figures above are read from the limiter''s own constants, not restated here — this string asserted that NO limit existed for a day after one shipped.'
  policy_url: https://scvd.store/developers
x-versioning:
  scheme: url-path
  note: 'Breaking changes arrive as a new version in the path (/api/preflight/v1 → /v2). A published version''s SHAPE never changes under a client: fields are added, never removed or retyped.'
  deprecation: A version being retired serves the RFC 8594 Deprecation and Sunset headers on every response for at least 90 days before it stops answering, and the date is published at /developers before the headers appear.
  sunset_headers:
  - Deprecation
  - Sunset
  - Link; rel="successor-version"
  policy_url: https://scvd.store/deprecation
  currently_deprecated: []
  versions:
  - path: /api/preflight/v1
    status: supported
    since: '2026-08-03'
    sunset: null
    successor: /api/preflight/v2
  - path: /api/preflight/v2
    status: current
    since: '2026-08-23'
    sunset: null
    successor: null
  - path: /api/look/v1
    status: current
    since: '2026-09-02'
    sunset: null
    successor: null
  - path: /api/conformance/v1
    status: current
    since: '2026-08-03'
    sunset: null
    successor: null