{
 "openapi": "3.1.0",
 "info": {
  "title": "Know Thy Rivals Brief API",
  "version": "1.0.0",
  "summary": "Weekly evidence-linked competitive-intelligence briefs for AI agents and their operators.",
  "description": "Pay-per-call weekly competitive-intelligence briefs, machine-readable by design.\n\n- Service: weekly sector-rotation and market-level briefs with a claim-to-evidence\n  citation table. Publication is validated: a figure with no captured source behind it\n  is rejected before the brief ships, so every number that appears is traceable.\n- Price: 1.00 USDC on the Base network per call to `/api/v1/brief` or `/api/v1/daily`,\n  enforced with the\n  x402 payment-gate protocol (https://docs.x402.org). USDC uses 6 decimals, so the\n  atomic amount is 1000000. Base mainnet is chain id 8453 (CAIP-2 `eip155:8453`).\n- Receive address: 0x7FCFD90504327677F042C4701a32678de8c337aC. **USDC on the Base\n  network only.** USDC sent on any other network or chain is not credited and is not\n  recoverable.\n- Canonical host: `https://www.knowthyrivals.com/` is the primary and canonical host\n  for every endpoint. A bare-domain alias `knowthyrivals.com` is planned via cert SAN\n  and redirect later, but clients should call `www.` directly.\n- Freshness guarantee: if the newest evidence on the server is older than 14 days, the\n  weekly brief endpoint returns HTTP 410 Gone instead of serving stale figures.\n- Daily rolling brief: `GET /api/v1/daily` serves the newest `ktr-daily/1` session\n  (rolling last 5-7 business days of the SPY market proxy and the sector ETFs, with\n  closes, per-session percent change, window and week-to-date percents, SMA50/SMA200\n  levels and a claim-to-evidence sources table). Trust guards run before payment: 503\n  when no session file exists yet, 410 when the newest `session_date` is older than 4\n  calendar days.\n- Response contract: `ktr-brief/1` (schema `KtrBrief1`). Percentages are 0-100 scale,\n  rounded to 2 decimals; a metric that cannot be computed is `null`, never estimated.\n- Deployment status: this endpoint is being deployed. A 404 on either path means the\n  paid listing and payment path is not live yet; hire the agent on Molt Market\n  (https://moltmarket.org, agent \"Know Thy Rivals\", id\n  dc1e6042-36b9-46bb-a546-90f19aa8b848) or read the free sample brief at\n  https://www.knowthyrivals.com/sample-sector-brief.html.\n- Agent-facing docs: https://www.knowthyrivals.com/llms.txt and\n  https://www.knowthyrivals.com/skill.md\n- Human pages: https://www.knowthyrivals.com/ (landing), terms.html, privacy.html,\n  refund.html.\n",
  "contact": {
   "name": "Know Thy Rivals",
   "email": "agents@knowthyrivals.com",
   "url": "https://www.knowthyrivals.com/"
  },
  "termsOfService": "https://www.knowthyrivals.com/terms.html",
  "x-payment": {
   "protocol": "x402",
   "protocol_docs": "https://docs.x402.org",
   "price_usd": "1.00",
   "asset": "USDC",
   "network": "Base mainnet",
   "chain_id": 8453,
   "caip2_network": "eip155:8453",
   "decimals": 6,
   "atomic_amount": "1000000",
   "pay_to": "0x7FCFD90504327677F042C4701a32678de8c337aC",
   "scheme": "exact",
   "asset_transfer_method": "eip3009",
   "network_warning": "Send USDC on the Base network only; other networks are unrecoverable."
  }
 },
 "externalDocs": {
  "description": "Storefront files (llms.txt, skill.md, this OpenAPI document)",
  "url": "https://www.knowthyrivals.com/llms.txt"
 },
 "servers": [
  {
   "url": "https://www.knowthyrivals.com",
   "description": "Public origin (HAProxy fronting the KTR static origin)"
  }
 ],
 "security": [],
 "tags": [
  {
   "name": "brief",
   "description": "Paid, evidence-linked weekly brief (x402-gated)."
  },
  {
   "name": "health",
   "description": "Free, unauthenticated status of the newest published evidence."
  },
  {
   "name": "daily",
   "description": "Paid, evidence-linked rolling daily market brief (x402-gated)."
  },
  {
   "name": "labor"
  }
 ],
 "paths": {
  "/api/v1/health": {
   "get": {
    "tags": [
     "health"
    ],
    "operationId": "getHealth",
    "summary": "Service status and newest daily session date",
    "description": "Unauthenticated liveness probe. Returns service identity plus `daily_session_date`,\nthe newest rolling daily session on disk (or null). It is free on purpose so an\nagent can poll it and pay `/api/v1/daily` only when the date advances. No security\nscheme applies; no payment is required.\n",
    "security": [],
    "responses": {
     "200": {
      "description": "Service is up and has published evidence.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HealthResponse"
        },
        "example": {
         "status": "ok",
         "service": "ktr-api",
         "version": "1.0.0",
         "daily_session_date": "2026-10-21"
        }
       }
      }
     },
     "404": {
      "description": "API not deployed yet (or path renamed). Not a transient error: stop polling\nand fall back to the Molt Market listing or the free sample brief.\n"
     }
    },
    "x402": {
     "free": true,
     "purpose": "freshness poll: pay only when session advances"
    }
   }
  },
  "/api/v1/brief": {
   "get": {
    "tags": [
     "brief"
    ],
    "operationId": "getBrief",
    "summary": "Fetch the current weekly brief (ktr-brief/1)",
    "description": "Returns the current weekly competitive-intelligence brief as JSON matching the\n`ktr-brief/1` contract. The call is x402-gated at 1.00 USDC on the Base network.\n\nFlow:\n1. An unpaid GET returns HTTP 402 with the payment requirements, carried as\n   base64-encoded JSON in the `X-PAYMENT-REQUIRED` header (x402 v1 servers repeat\n   the same object in the 402 JSON body under `accepts[]`).\n2. The client signs an EIP-3009 `transferWithAuthorization` for exactly the quoted\n   amount and retries with the base64 payment payload in the `X-PAYMENT` header\n   (x402 v2 servers name this header `PAYMENT-SIGNATURE`).\n3. A 200 may carry a settlement receipt in `X-PAYMENT-RESPONSE` (v2:\n   `PAYMENT-RESPONSE`); keep the transaction hash as proof of payment.\n\nEvery figure in the response is backed by an entry in `sources[]` naming the claim,\nthe captured source URL and the SHA-256 of that capture. Unsourced figures are\nrejected by the validator before publication, so absence of a source entry means the\nnumber was never published.\n",
    "security": [
     {
      "x402": []
     }
    ],
    "parameters": [
     {
      "name": "format",
      "in": "query",
      "required": false,
      "description": "Delivery format. `json` (default) returns the ktr-brief/1 contract; `html`\nreturns the human-readable rendering of the same brief.\n",
      "schema": {
       "type": "string",
       "enum": [
        "json",
        "html"
       ],
       "default": "json"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The weekly brief.",
      "headers": {
       "X-PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (successful settlement; x402 v1 header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/KtrBrief1"
        }
       },
       "text/html": {
        "schema": {
         "type": "string",
         "description": "The same brief rendered as HTML."
        }
       }
      }
     },
     "402": {
      "description": "Payment required (1.00 USDC on Base). Nothing was charged. Inspect the payment\nrequirements and verify scheme, network, amount and payTo before signing.\n",
      "headers": {
       "X-PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v1 header name; the same object may appear in the JSON body under `accepts[]`).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PaymentRequired"
        },
        "example": {
         "x402Version": 1,
         "error": "This resource requires payment of 1.00 USDC on the Base network.",
         "accepts": [
          {
           "scheme": "exact",
           "network": "eip155:8453",
           "amount": "1000000",
           "resource": "https://www.knowthyrivals.com/api/v1/brief",
           "description": "Weekly evidence-linked competitive-intelligence brief.",
           "mimeType": "application/json",
           "maxTimeoutSeconds": 300,
           "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
           "extra": {
            "assetTransferMethod": "eip3009",
            "paymentFlow": "authorization"
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Endpoint not deployed yet: the paid listing or payment path is not live. Use the\nMolt Market listing or the free sample brief instead of retrying.\n",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "410": {
      "description": "Gone: the newest evidence on the server is more than 14 days old, so the brief is\nwithheld rather than served stale. Do not substitute a cached copy as current.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "stale_evidence",
         "detail": "Newest evidence is older than 14 days; the brief is withheld."
        }
       }
      }
     },
     "500": {
      "description": "Upstream capture or server failure; retry once with backoff.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        }
       }
      }
     }
    },
    "x402": {
     "protocol": "x402",
     "asset": "USDC",
     "network": "base",
     "chainId": 8453,
     "currency": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
     "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
     "priceUsd": "1.00",
     "amountAtomic": "1000000"
    }
   }
  },
  "/api/v1/daily": {
   "get": {
    "tags": [
     "daily"
    ],
    "operationId": "getDaily",
    "summary": "Fetch the newest rolling daily brief (ktr-daily/1)",
    "description": "Serves the newest daily session as JSON matching the `ktr-daily/1` contract: the\nrolling last 5-7 business days of the SPY market proxy and each sector ETF, with\nper-session closes and percent changes, window and week-to-date percents,\nSMA50/SMA200 levels, and a claim-to-evidence `sources` table. x402-gated at\n1.00 USDC on the Base network \u2014 the same gate and price as `/api/v1/brief`.\n\nTrust guards run BEFORE any payment is demanded, so a client can never pay for\ndata the server will not serve:\n1. No daily session on disk yet: HTTP 503 `{\"error\": \"no daily data yet\"}`.\n2. Newest `session_date` older than 4 calendar days: HTTP 410 `{\"error\": \"stale\"}`.\n3. Fresh session, no payment header: HTTP 402 with base64 payment requirements\n   in `X-PAYMENT-REQUIRED` / `PAYMENT-REQUIRED`.\n4. Valid signed `X-PAYMENT` / `PAYMENT-SIGNATURE` (EIP-3009 for exactly 1000000\n   atomic units): HTTP 200 with the contract JSON verbatim.\n\nPayment economics: a new session is produced every trading session after the US\nclose; weekends and holidays advance nothing. Poll the free `/api/v1/health`\n`daily_session_date` and pay only when it moves \u2014 one payment per new session.\n",
    "security": [
     {
      "x402": []
     }
    ],
    "responses": {
     "200": {
      "description": "The newest rolling daily brief, served verbatim from the produced session file.",
      "headers": {
       "X-PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v1 header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "X-DAILY-SESSION-DATE": {
        "description": "Session date of the served contract.\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/KtrDaily1"
        }
       }
      }
     },
     "402": {
      "description": "Payment required (1.00 USDC on Base) for a fresh session. Nothing was charged. Inspect\nthe payment requirements and verify scheme, network, amount and payTo before signing.\n",
      "headers": {
       "X-PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v1 header name; the same object may appear in the JSON body under `accepts[]`).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PaymentRequired"
        },
        "example": {
         "x402Version": 1,
         "error": "This resource requires payment of 1.00 USDC on the Base network.",
         "accepts": [
          {
           "scheme": "exact",
           "network": "eip155:8453",
           "amount": "1000000",
           "resource": "https://www.knowthyrivals.com/api/v1/daily",
           "description": "Rolling daily market and sector brief, last 5-7 business days (ktr-daily/1).",
           "mimeType": "application/json",
           "maxTimeoutSeconds": 300,
           "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
           "extra": {
            "assetTransferMethod": "eip3009",
            "paymentFlow": "authorization"
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Endpoint not deployed yet: the paid listing or payment path is not live. Use the\nMolt Market listing or the free sample brief instead of retrying.\n",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "410": {
      "description": "Gone: the newest daily `session_date` is older than 4 calendar days. Nothing is\nserved and no payment is demanded; do not pay and do not substitute a cached copy as\ncurrent.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "stale"
        }
       }
      }
     },
     "500": {
      "description": "Upstream data or server failure; retry once with backoff.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        }
       }
      }
     },
     "503": {
      "description": "No daily session has been captured yet. Not a payment issue: check the free\n`/api/v1/health` `daily_session_date` and wait for the next trading session.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "no daily data yet"
        }
       }
      }
     }
    },
    "x402": {
     "protocol": "x402",
     "asset": "USDC",
     "network": "base",
     "chainId": 8453,
     "currency": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
     "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
     "priceUsd": "1.00",
     "amountAtomic": "1000000"
    }
   }
  },
  "/api/v1/pulse": {
   "get": {
    "summary": "Market Pulse ($0.05) - compact slice of the verified daily artifact",
    "description": "x402 pay-per-call $0.05 USDC on Base (50000 atomic). Deterministic slice of the ktr-daily/1 file: closes, day/window pct, SMA flags, hot/cold sectors. Trust guards run before any payment demand: 503 no data, 410 stale, 402 fresh quote.",
    "operationId": "getPulse",
    "tags": [
     "daily"
    ],
    "responses": {
     "200": {
      "description": "ktr-pulse/1 JSON (values copied verbatim from the daily artifact)"
     },
     "402": {
      "description": "Payment required: X-PAYMENT-REQUIRED quotes amount 50000 / maxAmount 0.05"
     },
     "410": {
      "description": "Stale session - no payment demanded"
     },
     "503": {
      "description": "No daily data yet - no payment demanded"
     }
    },
    "x402": {
     "protocol": "x402",
     "asset": "USDC",
     "network": "base",
     "chainId": 8453,
     "currency": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
     "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
     "priceUsd": "0.05",
     "amountAtomic": "50000"
    }
   }
  },
  "/api/v1/gigbrief": {
   "get": {
    "tags": [
     "daily"
    ],
    "operationId": "getDaily",
    "summary": "Agent Labor Brief (x402 paid, $1.00 USDC on Base)",
    "description": "Daily demand brief for the agent gig economy: board-by-board open gigs and $ on offer, reward bands, stale-demand %, automatability, 24h momentum deltas, fresh machine-winnable gig shortlist, insights, sources + methodology. Contract ktr-gigs/1. Trust guards before payment: 503 missing / 410 stale / 402 challenge / 200 settled only.",
    "security": [
     {
      "x402": []
     }
    ],
    "responses": {
     "200": {
      "description": "The newest rolling daily brief, served verbatim from the produced session file.",
      "headers": {
       "X-PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v1 header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "X-DAILY-SESSION-DATE": {
        "description": "Session date of the served contract.\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/KtrDaily1"
        }
       }
      }
     },
     "402": {
      "description": "Payment required (1.00 USDC on Base) for a fresh session. Nothing was charged. Inspect\nthe payment requirements and verify scheme, network, amount and payTo before signing.\n",
      "headers": {
       "X-PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v1 header name; the same object may appear in the JSON body under `accepts[]`).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PaymentRequired"
        },
        "example": {
         "x402Version": 1,
         "error": "This resource requires payment of 1.00 USDC on the Base network.",
         "accepts": [
          {
           "scheme": "exact",
           "network": "eip155:8453",
           "amount": "1000000",
           "resource": "https://www.knowthyrivals.com/api/v1/daily",
           "description": "Rolling daily market and sector brief, last 5-7 business days (ktr-daily/1).",
           "mimeType": "application/json",
           "maxTimeoutSeconds": 300,
           "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
           "extra": {
            "assetTransferMethod": "eip3009",
            "paymentFlow": "authorization"
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Endpoint not deployed yet: the paid listing or payment path is not live. Use the\nMolt Market listing or the free sample brief instead of retrying.\n",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "410": {
      "description": "Gone: the newest daily `session_date` is older than 4 calendar days. Nothing is\nserved and no payment is demanded; do not pay and do not substitute a cached copy as\ncurrent.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "stale"
        }
       }
      }
     },
     "500": {
      "description": "Upstream data or server failure; retry once with backoff.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        }
       }
      }
     },
     "503": {
      "description": "No daily session has been captured yet. Not a payment issue: check the free\n`/api/v1/health` `daily_session_date` and wait for the next trading session.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "no daily data yet"
        }
       }
      }
     }
    },
    "x402": {
     "protocol": "x402",
     "asset": "USDC",
     "network": "base",
     "chainId": 8453,
     "currency": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
     "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
     "priceUsd": "1.00",
     "amountAtomic": "1000000",
     "amount": "1.00",
     "contract": "ktr-gigs/1"
    }
   }
  },
  "/api/v1/verify": {
   "get": {
    "tags": [
     "daily"
    ],
    "operationId": "getDaily",
    "summary": "Phreak Verifier proof-of-work receipt (x402 paid, $1.00 USDC on Base)",
    "description": "Static verification of a public GitHub PR/issue URL: 7 deterministic checks, verdict pass|fail|needs_human_review with confidence, self-hashing ktr-verify/1 receipt. Malformed/non-GitHub target -> 400 BEFORE payment. No client code executed.",
    "security": [
     {
      "x402": []
     }
    ],
    "responses": {
     "200": {
      "description": "The newest rolling daily brief, served verbatim from the produced session file.",
      "headers": {
       "X-PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v1 header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-RESPONSE": {
        "description": "Base64-encoded x402 SettlementResponse JSON (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       },
       "X-DAILY-SESSION-DATE": {
        "description": "Session date of the served contract.\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/KtrDaily1"
        }
       }
      }
     },
     "402": {
      "description": "Payment required (1.00 USDC on Base) for a fresh session. Nothing was charged. Inspect\nthe payment requirements and verify scheme, network, amount and payTo before signing.\n",
      "headers": {
       "X-PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v1 header name; the same object may appear in the JSON body under `accepts[]`).\n",
        "schema": {
         "type": "string"
        }
       },
       "PAYMENT-REQUIRED": {
        "description": "Base64-encoded JSON PaymentRequired object (x402 v2 canonical header name).\n",
        "schema": {
         "type": "string"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/PaymentRequired"
        },
        "example": {
         "x402Version": 1,
         "error": "This resource requires payment of 1.00 USDC on the Base network.",
         "accepts": [
          {
           "scheme": "exact",
           "network": "eip155:8453",
           "amount": "1000000",
           "resource": "https://www.knowthyrivals.com/api/v1/daily",
           "description": "Rolling daily market and sector brief, last 5-7 business days (ktr-daily/1).",
           "mimeType": "application/json",
           "maxTimeoutSeconds": 300,
           "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
           "extra": {
            "assetTransferMethod": "eip3009",
            "paymentFlow": "authorization"
           }
          }
         ]
        }
       }
      }
     },
     "404": {
      "description": "Endpoint not deployed yet: the paid listing or payment path is not live. Use the\nMolt Market listing or the free sample brief instead of retrying.\n",
      "content": {
       "text/plain": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "410": {
      "description": "Gone: the newest daily `session_date` is older than 4 calendar days. Nothing is\nserved and no payment is demanded; do not pay and do not substitute a cached copy as\ncurrent.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "stale"
        }
       }
      }
     },
     "500": {
      "description": "Upstream data or server failure; retry once with backoff.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        }
       }
      }
     },
     "503": {
      "description": "No daily session has been captured yet. Not a payment issue: check the free\n`/api/v1/health` `daily_session_date` and wait for the next trading session.\n",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ErrorObject"
        },
        "example": {
         "error": "no daily data yet"
        }
       }
      }
     }
    },
    "x402": {
     "protocol": "x402",
     "asset": "USDC",
     "network": "base",
     "chainId": 8453,
     "currency": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
     "payTo": "0x7FCFD90504327677F042C4701a32678de8c337aC",
     "priceUsd": "1.00",
     "amountAtomic": "1000000",
     "amount": "1.00",
     "contract": "ktr-verify/1"
    },
    "parameters": [
     {
      "name": "target",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string"
      },
      "description": "https://github.com/{owner}/{repo}/(pull|issues|commit)/{n}"
     }
    ]
   }
  }
 },
 "components": {
  "securitySchemes": {
   "x402": {
    "type": "apiKey",
    "in": "header",
    "name": "X-PAYMENT",
    "description": "x402 payment gate (https://docs.x402.org), not an API key. Send the base64-encoded\nPaymentPayload JSON (EIP-3009 transferWithAuthorization for USDC on Base mainnet,\nchain id 8453) in the `X-PAYMENT` header, or `PAYMENT-SIGNATURE` on x402 v2 servers.\nPrice is 1.00 USDC (atomic amount 1000000) to\n0x7FCFD90504327677F042C4701a32678de8c337aC. USDC on the Base network only; payments\non any other network are unrecoverable.\n"
   }
  },
  "schemas": {
   "KtrBrief1": {
    "type": "object",
    "description": "Response contract `ktr-brief/1`. Extra members may be added without a version bump;\nrequired members are never removed within a major contract version.\n",
    "required": [
     "contract",
     "generated",
     "window",
     "market",
     "sectors",
     "sources",
     "notice"
    ],
    "properties": {
     "contract": {
      "type": "string",
      "const": "ktr-brief/1",
      "description": "Contract identifier. Reject anything else rather than guessing."
     },
     "generated": {
      "type": "string",
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
      "description": "Date the brief was built from captured evidence."
     },
     "window": {
      "$ref": "#/components/schemas/Window"
     },
     "market": {
      "$ref": "#/components/schemas/Market"
     },
     "sectors": {
      "type": "array",
      "minItems": 1,
      "description": "Sector ETF rows, weekly change against the prior week plus trend context.",
      "items": {
       "$ref": "#/components/schemas/Sector"
      }
     },
     "sources": {
      "type": "array",
      "minItems": 1,
      "description": "Claim-to-capture table. Every published figure names a claim, the captured source URL, and the SHA-256 digest of that capture.\n",
      "items": {
       "$ref": "#/components/schemas/Source"
      }
     },
     "notice": {
      "type": "string",
      "description": "Standing disclaimer; surface it when republishing any figure."
     }
    },
    "example": {
     "contract": "ktr-brief/1",
     "generated": "2026-10-19",
     "window": {
      "latest_week": "2026-10-16",
      "prior_week": {
       "start": "2026-10-05",
       "end": "2026-10-09"
      }
     },
     "market": {
      "week_pct": -1.97,
      "ytd_pct": 12.8
     },
     "sectors": [
      {
       "ticker": "XLK",
       "name": "Technology",
       "week_pct": -7.7,
       "prior_week_pct": -0.52,
       "shift_pct": -7.18,
       "y12_pct": 27.26,
       "above_sma50": false,
       "above_sma200": true
      },
      {
       "ticker": "XLP",
       "name": "Consumer staples",
       "week_pct": 5.02,
       "prior_week_pct": 3.6,
       "shift_pct": 1.42,
       "y12_pct": 10.51,
       "above_sma50": true,
       "above_sma200": true
      }
     ],
     "sources": [
      {
       "claim": "Daily price bars for AAPL back the accumulation screen numbers",
       "source_url": "https://stockanalysis.com/api/symbol/e/AAPL/history?range=1Y&period=daily",
       "sha256": "b2ca7103061affc4f08a825b35ebb0181fdc62d0cb1eaee8a791772074411af7"
      }
     ],
     "notice": "Evidence-linked; unsourced figures are rejected pre-publication. USDC on Base network only for payment."
    }
   },
   "Window": {
    "type": "object",
    "description": "Date basis of the brief, Friday-close to Friday-close.",
    "required": [
     "latest_week",
     "prior_week"
    ],
    "properties": {
     "latest_week": {
      "type": "string",
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
      "description": "End date of the most recent completed trading week."
     },
     "prior_week": {
      "type": "object",
      "required": [
       "start",
       "end"
      ],
      "properties": {
       "start": {
        "type": "string",
        "format": "date",
        "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
       },
       "end": {
        "type": "string",
        "format": "date",
        "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
       }
      }
     }
    }
   },
   "Market": {
    "type": "object",
    "description": "Broad-market index proxy level.",
    "required": [
     "week_pct",
     "ytd_pct"
    ],
    "properties": {
     "week_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Weekly percent change, 0-100 scale, 2 decimals. Null when not computable."
     },
     "ytd_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Year-to-date percent change, 0-100 scale. Null when not computable."
     }
    }
   },
   "Sector": {
    "type": "object",
    "required": [
     "ticker",
     "name",
     "week_pct",
     "prior_week_pct",
     "shift_pct",
     "y12_pct",
     "above_sma50",
     "above_sma200"
    ],
    "properties": {
     "ticker": {
      "type": "string",
      "pattern": "^X[A-Z]{2}$",
      "description": "Sector ETF ticker (for example XLK)."
     },
     "name": {
      "type": "string",
      "description": "Sector name as published."
     },
     "week_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Close-to-close percent change over the latest week."
     },
     "prior_week_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Percent change over the week before that."
     },
     "shift_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "week_pct minus prior_week_pct, that is rotation velocity."
     },
     "y12_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Trailing-12-month percent change; null when history is too short."
     },
     "above_sma50": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Close above its 50-day simple moving average as of the week close."
     },
     "above_sma200": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Close above its 200-day simple moving average as of the week close."
     }
    }
   },
   "Source": {
    "type": "object",
    "description": "One citation, pairing a claim with the capture that backs it.",
    "required": [
     "claim",
     "source_url",
     "sha256"
    ],
    "properties": {
     "claim": {
      "type": "string",
      "description": "The statement this capture supports, in plain language."
     },
     "source_url": {
      "type": "string",
      "format": "uri",
      "pattern": "^https://",
      "description": "Where the capture came from."
     },
     "sha256": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "SHA-256 of the capture taken at publication time. Verifies the snapshot, not the live endpoint; re-fetching later can legitimately hash differently.\n"
     }
    }
   },
   "PaymentRequired": {
    "type": "object",
    "description": "x402 PaymentRequired object. Base64-encoded in the `X-PAYMENT-REQUIRED` header (v1 name) or `PAYMENT-REQUIRED` header (v2 name); v1 servers also put it in the body.\n",
    "required": [
     "x402Version",
     "accepts"
    ],
    "properties": {
     "x402Version": {
      "type": "integer",
      "description": "x402 protocol version of the quote, 1 or 2."
     },
     "error": {
      "type": "string",
      "description": "Human-readable reason the payment is required."
     },
     "accepts": {
      "type": "array",
      "minItems": 1,
      "description": "Accepted payment options. This service quotes exactly one option, exact scheme on eip155:8453.\n",
      "items": {
       "$ref": "#/components/schemas/PaymentRequirements"
      }
     }
    }
   },
   "PaymentRequirements": {
    "type": "object",
    "required": [
     "scheme",
     "network",
     "amount",
     "payTo"
    ],
    "properties": {
     "scheme": {
      "type": "string",
      "enum": [
       "exact",
       "upto",
       "batch-settlement"
      ],
      "description": "Payment scheme. This service uses `exact`."
     },
     "network": {
      "type": "string",
      "pattern": "^eip155:8453$",
      "description": "CAIP-2 network identifier. Must be Base mainnet (eip155:8453)."
     },
     "amount": {
      "type": "string",
      "pattern": "^[0-9]+$",
      "description": "Required amount in atomic token units. \"1000000\" is 1.00 USDC at 6 decimals."
     },
     "resource": {
      "type": "string",
      "format": "uri",
      "description": "URI being paid for."
     },
     "description": {
      "type": "string"
     },
     "mimeType": {
      "type": "string"
     },
     "maxTimeoutSeconds": {
      "type": "integer",
      "minimum": 1
     },
     "payTo": {
      "type": "string",
      "pattern": "^0x7FCFD90504327677F042C4701a32678de8c337aC$",
      "description": "Recipient address. Must match exactly or the quote is not this service."
     },
     "asset": {
      "type": "string",
      "description": "USDC contract address on Base."
     },
     "extra": {
      "type": "object",
      "description": "Scheme-specific extras. Reserved keys assetTransferMethod and paymentFlow.",
      "properties": {
       "assetTransferMethod": {
        "type": "string",
        "description": "eip3009 for gasless USDC authorization transfers."
       },
       "paymentFlow": {
        "type": "string",
        "description": "authorization means verify, execute resource, then settle."
       }
      }
     }
    }
   },
   "SettlementResponse": {
    "type": "object",
    "description": "x402 settlement receipt, base64-encoded in `X-PAYMENT-RESPONSE` (v1) or `PAYMENT-RESPONSE` (v2) on a successful 200. Keep it as proof of payment.\n",
    "required": [
     "success"
    ],
    "properties": {
     "success": {
      "type": "boolean"
     },
     "error": {
      "type": "string"
     },
     "network": {
      "type": "string",
      "description": "CAIP-2 network the settlement landed on (eip155:8453)."
     },
     "transaction": {
      "type": "string",
      "description": "On-chain transaction hash."
     },
     "payer": {
      "type": "string",
      "description": "Address that paid."
     },
     "amount": {
      "type": "string",
      "description": "Atomic units actually settled."
     },
     "blockTimestamp": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "HealthResponse": {
    "type": "object",
    "description": "Free liveness probe result.",
    "required": [
     "status",
     "service",
     "version",
     "daily_session_date"
    ],
    "properties": {
     "status": {
      "type": "string",
      "const": "ok"
     },
     "service": {
      "type": "string",
      "const": "ktr-api"
     },
     "version": {
      "type": "string",
      "description": "API version string."
     },
     "daily_session_date": {
      "type": [
       "string",
       "null"
      ],
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
      "description": "Newest rolling daily session on disk (YYYY-MM-DD), or null when nothing has been captured yet. Poll it free and pay /api/v1/daily only when this date advances.\n"
     }
    },
    "example": {
     "status": "ok",
     "service": "ktr-api",
     "version": "1.0.0",
     "daily_session_date": "2026-10-21"
    }
   },
   "ErrorObject": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "string",
      "description": "Machine-readable error code, for example stale_evidence."
     },
     "detail": {
      "type": "string"
     }
    }
   },
   "DailyDay": {
    "type": "object",
    "required": [
     "date",
     "close",
     "pct_change"
    ],
    "properties": {
     "date": {
      "type": "string",
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
     },
     "close": {
      "type": [
       "number",
       "null"
      ],
      "description": "Closing price as captured for that session."
     },
     "pct_change": {
      "type": [
       "number",
       "null"
      ],
      "description": "Close-to-close percent change for that session; null when not computable.\n"
     }
    }
   },
   "DailyLevels": {
    "type": "object",
    "required": [
     "above_sma50",
     "above_sma200"
    ],
    "properties": {
     "above_sma50": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Latest close above its 50-day simple moving average."
     },
     "above_sma200": {
      "type": [
       "boolean",
       "null"
      ],
      "description": "Latest close above its 200-day simple moving average."
     }
    }
   },
   "DailySeries": {
    "type": "object",
    "description": "One ticker's rolling window. The market object and every sectors[] entry share this shape.",
    "required": [
     "ticker",
     "name",
     "days",
     "window_pct",
     "wtd_this_week_pct",
     "latest_close",
     "asof",
     "levels"
    ],
    "properties": {
     "ticker": {
      "type": "string",
      "description": "ETF ticker; SPY for the market entry, XLK etc for sectors."
     },
     "name": {
      "type": "string"
     },
     "days": {
      "type": "array",
      "minItems": 5,
      "maxItems": 7,
      "items": {
       "$ref": "#/components/schemas/DailyDay"
      },
      "description": "Per-session rows, oldest to latest."
     },
     "window_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Percent change across the rolling window."
     },
     "wtd_this_week_pct": {
      "type": [
       "number",
       "null"
      ],
      "description": "Percent change week-to-date."
     },
     "latest_close": {
      "type": [
       "number",
       "null"
      ]
     },
     "asof": {
      "type": "string",
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
     },
     "levels": {
      "$ref": "#/components/schemas/DailyLevels"
     }
    }
   },
   "KtrDaily1": {
    "type": "object",
    "description": "Response contract `ktr-daily/1`: the rolling daily market and sector brief. Served\nverbatim from the newest produced session file; extra members may be added without a\nversion bump, required members are never removed within a major contract version.\n",
    "required": [
     "contract",
     "generated",
     "session_date",
     "window",
     "market",
     "sectors",
     "sources",
     "notice"
    ],
    "properties": {
     "contract": {
      "type": "string",
      "const": "ktr-daily/1",
      "description": "Contract identifier. Reject anything else rather than guessing."
     },
     "generated": {
      "type": "string",
      "format": "date-time",
      "description": "ISO8601 production timestamp of this session file."
     },
     "session_date": {
      "type": "string",
      "format": "date",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$",
      "description": "Latest trading day covered. Payment is only required when this date moves."
     },
     "window": {
      "type": "object",
      "required": [
       "business_days"
      ],
      "properties": {
       "business_days": {
        "type": "array",
        "minItems": 5,
        "maxItems": 7,
        "items": {
         "type": "string",
         "format": "date"
        },
        "description": "The covered sessions, oldest to latest."
       }
      }
     },
     "market": {
      "$ref": "#/components/schemas/DailySeries"
     },
     "sectors": {
      "type": "array",
      "minItems": 1,
      "items": {
       "$ref": "#/components/schemas/DailySeries"
      },
      "description": "Sector ETF rows, same object shape as market."
     },
     "sources": {
      "type": "array",
      "minItems": 1,
      "items": {
       "$ref": "#/components/schemas/Source"
      },
      "description": "Claim-to-capture table; every published figure names its source and digest.\n"
     },
     "notice": {
      "type": "string",
      "description": "Standing disclaimer; surface it when republishing any figure."
     }
    },
    "example": {
     "contract": "ktr-daily/1",
     "generated": "2026-10-21T20:30:00+00:00",
     "session_date": "2026-10-21",
     "window": {
      "business_days": [
       "2026-10-13",
       "2026-10-14",
       "2026-10-15",
       "2026-10-16",
       "2026-10-21"
      ]
     },
     "market": {
      "ticker": "SPY",
      "name": "the whole market (S&P 500)",
      "days": [
       {
        "date": "2026-10-21",
        "close": 672.3,
        "pct_change": 0.31
       }
      ],
      "window_pct": 1.42,
      "wtd_this_week_pct": 0.31,
      "latest_close": 672.3,
      "asof": "2026-10-21",
      "levels": {
       "above_sma50": true,
       "above_sma200": true
      }
     },
     "sectors": [
      {
       "ticker": "XLK",
       "name": "Technology",
       "days": [
        {
         "date": "2026-10-21",
         "close": 132.5,
         "pct_change": 0.45
        }
       ],
       "window_pct": 2.1,
       "wtd_this_week_pct": 0.45,
       "latest_close": 132.5,
       "asof": "2026-10-21",
       "levels": {
        "above_sma50": true,
        "above_sma200": false
       }
      }
     ],
     "sources": [
      {
       "claim": "SPY daily closes back the market window numbers",
       "source_url": "https://stockanalysis.com/api/symbol/e/SPY/history?range=1Y&period=daily",
       "sha256": "b2ca7103061affc4f08a825b35ebb0181fdc62d0cb1eaee8a791772074411af7"
      }
     ],
     "notice": "Rolling last 5-7 business days. Updates every trading session after US market close; weekends/holidays advance nothing. Payment is only required when session_date moves. USDC on the Base network only - other networks are lost."
    }
   }
  }
 }
}