openapi: 3.1.0
info:
  title: CHAIN4663 RWA WATCH API
  version: 1.4.0
  description: Deterministic operational data for canonical Robinhood Chain stock tokens and tokenized ETFs. Public API and MCP access is limited to 120 requests per 60 seconds per anonymous client and Cloudflare location. Not investment advice.
servers:
  - url: https://chain4663.com
paths:
  /api/v1/meta:
    get:
      summary: Service and chain metadata
      responses:
        '200': {description: Service metadata}
        '429': {$ref: '#/components/responses/RateLimited'}
  /health:
    get:
      summary: Fail-closed service readiness
      responses:
        '200': {description: Ready}
        '503': {description: Not ready}
  /api/v1/assets:
    get:
      summary: List accepted canonical assets and latest state
      responses:
        '200': {description: Asset collection}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/assets/{symbol}:
    get:
      summary: Read one canonical asset
      parameters:
        - in: path
          name: symbol
          required: true
          schema: {type: string, pattern: '^[A-Z0-9]{1,10}$'}
      responses:
        '200': {description: Asset}
        '404': {description: Not found}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/assets/{symbol}/history:
    get:
      summary: Validated Robinhood underlying-market OHLCV history
      parameters:
        - in: path
          name: symbol
          required: true
          schema: {type: string, pattern: '^[A-Z0-9]{1,10}$'}
        - in: query
          name: range
          schema: {type: string, enum: [1D, 1W, 1M, 3M, 1Y, 5Y], default: 1M}
      responses:
        '200': {description: Validated OHLCV bars or an explicit unavailable state}
        '400': {description: Invalid range}
        '404': {description: Canonical asset not found}
        '502': {description: Upstream history unavailable or invalid}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/assets/{symbol}/metrics:
    get:
      summary: Hourly Blockscout holder, transfer, supply, price-field, and volume history for one canonical asset
      parameters:
        - in: path
          name: symbol
          required: true
          schema: {type: string, pattern: '^[A-Z0-9]{1,10}$'}
        - in: query
          name: days
          schema: {type: integer, minimum: 1, maximum: 365, default: 30}
      responses:
        '200': {description: Per-asset hourly explorer metric history}
        '404': {description: Canonical asset not found}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/metrics:
    get:
      summary: Canonical RWA holder, transfer, volume, reference-notional, and whole-chain context metrics
      responses:
        '200': {description: Coverage-labeled analytics and seven-day hourly history}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/collisions:
    get:
      summary: Exact-ticker contracts that do not match canonical registry addresses
      responses:
        '200': {description: Deterministic identity warnings and scan coverage}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/listings:
    get:
      summary: Canonical registry listing chronology
      responses:
        '200': {description: First-seen registry observations and asset-addition event IDs}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/peg:
    get:
      summary: Deterministic token-venue price comparison eligibility
      responses:
        '200': {description: Peg comparison coverage, policy, exclusions, and eligible observations}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/issuance:
    get:
      summary: Per-asset canonical contract supply and Blockscout reconciliation
      responses:
        '200': {description: Issuance coverage, reconciliation state, and recent deterministic supply-change events}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/verify/{address}:
    get:
      summary: Check whether an address is in the accepted canonical registry
      parameters:
        - in: path
          name: address
          required: true
          schema: {type: string, pattern: '^0x[0-9a-fA-F]{40}$'}
      responses:
        '200': {description: Verification result}
        '400': {description: Malformed address}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/events:
    get:
      summary: List public deterministic events
      parameters:
        - {in: query, name: since, schema: {type: string, format: date-time}}
        - {in: query, name: symbol, schema: {type: string}}
        - {in: query, name: type, schema: {type: string}}
        - {in: query, name: id, schema: {type: string}}
        - {in: query, name: limit, schema: {type: integer, minimum: 1, maximum: 500, default: 100}}
      responses:
        '200': {description: Event collection}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/actions:
    get:
      summary: List scheduled and applied corporate-action events
      responses:
        '200': {description: Action event collection}
        '429': {$ref: '#/components/responses/RateLimited'}
  /api/v1/status:
    get:
      summary: Aggregate source coverage and readiness status
      responses:
        '200': {description: Status summary}
        '429': {$ref: '#/components/responses/RateLimited'}
  /rss.xml:
    get:
      summary: RSS 2.0 event feed
      responses:
        '200': {description: RSS document}
  /assets/{symbol}/rss.xml:
    get:
      summary: Per-asset RSS 2.0 event feed
      parameters:
        - in: path
          name: symbol
          required: true
          schema: {type: string, pattern: '^[A-Z0-9]{1,10}$'}
      responses:
        '200': {description: Ticker RSS document}
        '404': {description: Canonical asset not found}
  /calendar.ics:
    get:
      summary: Global corporate-actions iCalendar subscription
      responses:
        '200': {description: iCalendar document}
  /assets/{symbol}/calendar.ics:
    get:
      summary: Per-asset corporate-actions iCalendar subscription
      parameters:
        - in: path
          name: symbol
          required: true
          schema: {type: string, pattern: '^[A-Z0-9]{1,10}$'}
      responses:
        '200': {description: Ticker iCalendar document}
        '404': {description: Canonical asset not found}
  /tokenlist.json:
    get:
      summary: Signed Uniswap-compatible canonical token list
      responses:
        '200': {description: Canonical token list with P-256 signature metadata}
  /data/latest.json:
    get:
      summary: Current canonical registry and onchain-state export
      responses:
        '200': {description: Open data JSON snapshot}
  /data/latest.csv:
    get:
      summary: Current canonical registry and onchain-state CSV export
      responses:
        '200': {description: Open data CSV snapshot}
  /data/manifest.json:
    get:
      summary: Daily open-data archive manifest with content hashes
      responses:
        '200': {description: Snapshot archive manifest}
  /data/address-labels.json:
    get:
      summary: Canonical RWA and observed exact-ticker collision address labels
      responses:
        '200': {description: Source-bound address label dataset}
components:
  responses:
    RateLimited:
      description: Public API request limit exceeded
      headers:
        RateLimit-Limit: {schema: {type: integer, example: 120}}
        RateLimit-Policy: {schema: {type: string, example: '120;w=60'}}
        RateLimit-Remaining: {schema: {type: integer, example: 0}}
        RateLimit-Reset: {schema: {type: integer, example: 60}}
        Retry-After: {schema: {type: integer, example: 60}}
