openapi: 3.1.0
info:
  title: witnessd
  version: 0.1.0
  description: >
    A neutral, machine-payable witness for the machine-readable web. Independent fetch,
    hash, timestamp, archive; hourly Merkle anchoring on Base. Paid endpoints respond
    402 with x402 payment requirements (USDC); alternatively send X-Api-Key credits.
servers:
  - url: https://REPLACE_WITH_YOUR_DOMAIN
paths:
  /api/witness:
    post:
      summary: Witness a URL or API response now ($0.02 via x402, or 2¢ credits)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [url]
              properties:
                url: { type: string, format: uri }
      responses:
        '201':
          description: Snapshot created; certificate returned (anchor proof appears after next hourly batch)
        '402': { description: x402 payment required / insufficient credits }
        '422': { description: Capture refused or failed (bad_url, blocked_address, too_large, timeout…) }
  /api/certificate/{id}:
    get:
      summary: Signed certificate incl. Merkle proof + anchor tx (free)
      parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
      responses:
        '200': { description: witnessd-certificate-v1 JSON }
        '404': { description: Unknown snapshot id }
  /api/retrieve/{id}:
    get:
      summary: Archived body + certificate ($0.05 via x402, or 5¢ credits). Add ?raw=1 for the raw body.
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
        - { name: raw, in: query, required: false, schema: { type: string, enum: ['1'] } }
      responses:
        '200': { description: '{certificate, body_base64} or raw body with original content-type' }
        '402': { description: Payment required }
        '404': { description: Unknown snapshot id }
  /api/credits:
    post:
      summary: Buy a prepaid credit pack ($1.00 via x402) → API key with 100¢ credit
      responses:
        '201': { description: '{api_key, credits_cents}' }
  /api/watch:
    post:
      summary: Scheduled witnessing (prepaid credits; respects robots.txt)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [url, interval_minutes, count]
              properties:
                url: { type: string, format: uri }
                interval_minutes: { type: integer, minimum: 10 }
                count: { type: integer, minimum: 1, maximum: 1000 }
      responses:
        '201': { description: Watch created; each firing produces a snapshot }
        '402': { description: Insufficient credits }
        '403': { description: robots.txt disallows recurring fetches of that path }
  /api/pubkey:
    get:
      summary: Service Ed25519 public key (free)
      responses: { '200': { description: '{alg, spki_b64}' } }
