{
  "openapi": "3.1.0",
  "info": {
    "title": "$ELEC — US National Electricity Price Index API",
    "version": "1.0.0",
    "description": "$ELEC is a real-time US national electricity price index delivered as a pay-per-use API feed. It ingests full market data from 12 major US power hub contracts traded on ICE, runs a proprietary liquidity-weighted blending algorithm, and publishes a single composite mid-price in USD/MWh every 0.5 seconds.\n\n## Payment Model\n\n$ELEC uses the **x402 protocol** for access control — an open HTTP payment standard settled in USDC on-chain (Base network). A single payment authorizes a time-bounded streaming session or a snapshot query. No accounts, no API keys, no invoicing.\n\n## Quick Start for AI Agents\n\n1. Call `POST /api/elec/stream/access` — server returns HTTP 402 with payment details.\n2. Pay the quoted USDC amount on Base using any x402-compatible wallet or library.\n3. Server issues a signed JWT session token.\n4. Use the token to either:\n   - Stream live prices: `GET /api/elec/stream?token=<JWT>` (SSE)\n   - Poll current price: `GET /api/elec/price?token=<JWT>` (JSON snapshot)\n\n## Input Markets\n\n$ELEC is derived from 12 ICE power hub contracts: PJM West Hub, PJM AEP-Dayton, ERCOT North, ERCOT Houston, CAISO NP15, CAISO SP15, MISO Indiana, MISO Minnesota, NYISO Zone A, NYISO Zone J (NYC), ISO-NE Mass Hub, SPP South Hub.",
    "contact": {
      "name": "ELEC Finance",
      "url": "https://elec.finance",
      "email": "api@elec.finance"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://elec.finance/terms"
    },
    "x-logo": {
      "url": "https://elec.finance/logo.png"
    }
  },
  "servers": [
    {
      "url": "https://api.elec.finance",
      "description": "Production"
    },
    {
      "url": "https://sandbox.elec.finance",
      "description": "Sandbox (mock data, no payment required)"
    }
  ],
  "tags": [
    {
      "name": "Access",
      "description": "Obtain a session token via x402 payment"
    },
    {
      "name": "Price",
      "description": "Retrieve the $ELEC index price"
    },
    {
      "name": "Stream",
      "description": "Real-time SSE price stream"
    },
    {
      "name": "Status",
      "description": "Feed health and index status"
    }
  ],
  "paths": {
    "/api/elec/stream/access": {
      "post": {
        "operationId": "requestAccess",
        "tags": ["Access"],
        "summary": "Request a session token (x402 payment flow)",
        "description": "Initiates the x402 payment flow to obtain a JWT session token. The server returns HTTP 402 with the USDC amount and recipient wallet address. The client completes the on-chain payment using an x402-compatible library; the Coinbase x402 facilitator verifies settlement and the server issues a signed JWT.\n\nFor AI agents: use the `coinbase/x402` npm package or the `x402-python` library to complete payment programmatically.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AccessRequest"
              },
              "example": {
                "session_window": "1h",
                "wallet_address": "0xAbC123..."
              }
            }
          }
        },
        "responses": {
          "402": {
            "description": "Payment required. Contains payment details for the x402 flow.",
            "headers": {
              "X-Payment-Required": {
                "description": "Signals x402 payment is required",
                "schema": { "type": "string", "example": "true" }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRequired"
                },
                "example": {
                  "x402_version": "1",
                  "error": "Payment Required",
                  "accepts": [
                    {
                      "scheme": "exact",
                      "network": "base-mainnet",
                      "max_amount_required": "2500000",
                      "asset": {
                        "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                        "decimals": 6,
                        "eip712_domain": {
                          "name": "USD Coin",
                          "version": "2"
                        }
                      },
                      "extra": {
                        "name": "$ELEC 1-Hour Session",
                        "description": "Real-time US electricity price feed — 1 hour access window"
                      },
                      "pay_to": "0xELECFinanceVaultAddress...",
                      "expires_at": "2026-07-01T14:10:00Z"
                    }
                  ]
                }
              }
            }
          },
          "200": {
            "description": "Payment verified. Session token issued.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionToken"
                },
                "example": {
                  "token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "session_id": "elec-stream-a1b2c3d4",
                  "expires_at": "2026-07-01T15:00:00Z",
                  "session_window_minutes": 60
                }
              }
            }
          },
          "400": {
            "description": "Bad request — invalid session_window or missing wallet_address.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/api/elec/price": {
      "get": {
        "operationId": "getCurrentPrice",
        "tags": ["Price"],
        "summary": "Get the current $ELEC index price (JSON snapshot)",
        "description": "Returns the most recent $ELEC composite index price as a single JSON object. Ideal for AI agents and automated systems that need a point-in-time price without maintaining a streaming connection.\n\nRequires a valid session token (JWT) obtained via the x402 payment flow. Pass the token in the `Authorization` header or as a query parameter.",
        "security": [
          { "BearerToken": [] },
          { "TokenParam": [] }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": false,
            "description": "JWT session token (alternative to Authorization header).",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Current $ELEC index price.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceMessage"
                },
                "example": {
                  "feed": {
                    "provider": "ELEC",
                    "version": "1.0",
                    "published_at": "2026-07-01T14:05:00.0000Z",
                    "interval_start_utc": "2026-07-01T14:04:59.5000Z",
                    "interval_end_utc": "2026-07-01T14:05:00.0000Z",
                    "interval_type": "0.5SEC",
                    "message_id": "elec-20260701-140500-001"
                  },
                  "elec_index": {
                    "price": 44.3021,
                    "unit": "USD/MWh",
                    "currency": "USD",
                    "contracts_included": 12,
                    "is_provisional": false
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session token.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "402": {
            "description": "Session token expired. Re-initiate x402 payment.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/api/elec/stream": {
      "get": {
        "operationId": "streamPrices",
        "tags": ["Stream"],
        "summary": "Subscribe to real-time $ELEC price stream (SSE)",
        "description": "Opens a Server-Sent Events (SSE) connection that delivers $ELEC price messages every 0.5 seconds for the duration of the session token.\n\n**SSE Event Types:**\n- `price` — $ELEC index tick (see PriceMessage schema)\n- `heartbeat` — sent every 30 seconds with session expiry info\n- `expiry_warning` — sent 5 minutes before token expiry\n- `session_ended` — sent on token expiry; client should re-pay\n- `maintenance` — server maintenance; client should retry after delay\n\nRequires a valid session token obtained via the x402 payment flow.",
        "security": [
          { "BearerToken": [] },
          { "TokenParam": [] }
        ],
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": false,
            "description": "JWT session token.",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "SSE stream open. Server pushes price events every 0.5 seconds.",
            "headers": {
              "Content-Type": {
                "schema": { "type": "string", "example": "text/event-stream" }
              },
              "Cache-Control": {
                "schema": { "type": "string", "example": "no-cache" }
              },
              "Connection": {
                "schema": { "type": "string", "example": "keep-alive" }
              }
            },
            "content": {
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "Stream of SSE-formatted events. Each event has `event:` and `data:` lines. The `data:` field is a JSON object matching PriceMessage (for `price` events) or HeartbeatMessage (for `heartbeat` events).",
                  "example": "event: price\ndata: {\"feed\":{\"provider\":\"ELEC\",\"version\":\"1.0\",\"published_at\":\"2026-07-01T14:05:00.0000Z\",\"interval_start_utc\":\"2026-07-01T14:04:59.5000Z\",\"interval_end_utc\":\"2026-07-01T14:05:00.0000Z\",\"interval_type\":\"0.5SEC\",\"message_id\":\"elec-20260701-140500-001\"},\"elec_index\":{\"price\":44.3021,\"unit\":\"USD/MWh\",\"currency\":\"USD\",\"contracts_included\":12,\"is_provisional\":false}}\n\nevent: heartbeat\ndata: {\"timestamp\":\"2026-07-01T14:05:30.0000Z\",\"session_expires_at\":\"2026-07-01T15:00:00Z\"}\n\n"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid session token.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          },
          "402": {
            "description": "Session token expired.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" }
              }
            }
          }
        }
      }
    },
    "/api/elec/status": {
      "get": {
        "operationId": "getStatus",
        "tags": ["Status"],
        "summary": "Get feed health and index status",
        "description": "Returns the current operational status of the $ELEC feed, including the number of active hub contracts, last published tick timestamp, and any provisional flags. No authentication required.",
        "responses": {
          "200": {
            "description": "Feed status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedStatus"
                },
                "example": {
                  "status": "operational",
                  "contracts_active": 12,
                  "contracts_total": 12,
                  "is_provisional": false,
                  "last_tick_at": "2026-07-01T14:05:00.0000Z",
                  "feed_version": "1.0",
                  "latency_ms": 12
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT session token issued after x402 payment. Pass as `Authorization: Bearer <token>`."
      },
      "TokenParam": {
        "type": "apiKey",
        "in": "query",
        "name": "token",
        "description": "JWT session token as query parameter (alternative to Authorization header)."
      }
    },
    "schemas": {
      "AccessRequest": {
        "type": "object",
        "required": ["session_window", "wallet_address"],
        "properties": {
          "session_window": {
            "type": "string",
            "enum": ["1h", "4h", "24h"],
            "description": "Duration of the access session. Determines the USDC price charged.",
            "example": "1h"
          },
          "wallet_address": {
            "type": "string",
            "description": "Client's EVM wallet address that will sign the x402 payment.",
            "example": "0xAbC123..."
          }
        }
      },
      "PaymentRequired": {
        "type": "object",
        "description": "x402 payment challenge returned with HTTP 402. Pass to an x402 client library to complete payment.",
        "properties": {
          "x402_version": {
            "type": "string",
            "example": "1"
          },
          "error": {
            "type": "string",
            "example": "Payment Required"
          },
          "accepts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentOption"
            }
          }
        }
      },
      "PaymentOption": {
        "type": "object",
        "properties": {
          "scheme": {
            "type": "string",
            "example": "exact"
          },
          "network": {
            "type": "string",
            "example": "base-mainnet"
          },
          "max_amount_required": {
            "type": "string",
            "description": "USDC amount in smallest unit (6 decimals). E.g. '2500000' = 2.50 USDC.",
            "example": "2500000"
          },
          "asset": {
            "type": "object",
            "properties": {
              "address": {
                "type": "string",
                "description": "USDC contract address on the specified network.",
                "example": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
              },
              "decimals": {
                "type": "integer",
                "example": 6
              }
            }
          },
          "pay_to": {
            "type": "string",
            "description": "ELEC Finance vault address to send payment to.",
            "example": "0xELECFinanceVaultAddress..."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Payment offer expiry. Client must complete payment before this time.",
            "example": "2026-07-01T14:10:00Z"
          }
        }
      },
      "SessionToken": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Signed JWT session token. Use in Authorization header or `token` query param.",
            "example": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
          },
          "session_id": {
            "type": "string",
            "description": "Unique session identifier.",
            "example": "elec-stream-a1b2c3d4"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp when this token expires.",
            "example": "2026-07-01T15:00:00Z"
          },
          "session_window_minutes": {
            "type": "integer",
            "description": "Session duration in minutes.",
            "example": 60
          }
        }
      },
      "Feed": {
        "type": "object",
        "description": "Metadata block present in every $ELEC price message.",
        "required": ["provider", "version", "published_at", "interval_start_utc", "interval_end_utc", "interval_type", "message_id"],
        "properties": {
          "provider": {
            "type": "string",
            "description": "Always 'ELEC'.",
            "example": "ELEC"
          },
          "version": {
            "type": "string",
            "description": "Schema version. Currently '1.0'.",
            "example": "1.0"
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp when $ELEC published this message. Sub-second precision (4 decimal places).",
            "example": "2026-07-01T14:05:00.0000Z"
          },
          "interval_start_utc": {
            "type": "string",
            "format": "date-time",
            "description": "Start of the 0.5-second pricing interval.",
            "example": "2026-07-01T14:04:59.5000Z"
          },
          "interval_end_utc": {
            "type": "string",
            "format": "date-time",
            "description": "End of the 0.5-second pricing interval.",
            "example": "2026-07-01T14:05:00.0000Z"
          },
          "interval_type": {
            "type": "string",
            "description": "Interval granularity. v1.0 is always '0.5SEC'. Future versions will add 'HOURLY', 'DA_HOURLY', 'EOD'.",
            "example": "0.5SEC"
          },
          "message_id": {
            "type": "string",
            "description": "Unique ID per tick. Use for deduplication and gap detection.",
            "example": "elec-20260701-140500-001"
          }
        }
      },
      "ElecIndex": {
        "type": "object",
        "description": "The $ELEC index price data block.",
        "required": ["price", "unit", "currency", "contracts_included", "is_provisional"],
        "properties": {
          "price": {
            "type": "number",
            "format": "float",
            "description": "The $ELEC composite index price in USD/MWh. Liquidity-weighted mid-price across all contributing hub contracts. 4 decimal precision.",
            "example": 44.3021
          },
          "unit": {
            "type": "string",
            "description": "Always 'USD/MWh'.",
            "example": "USD/MWh"
          },
          "currency": {
            "type": "string",
            "description": "Base currency. Currently 'USD'.",
            "example": "USD"
          },
          "contracts_included": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "description": "Number of hub contracts that contributed to this tick. Max 12. Drops below 12 if a hub feed is stale.",
            "example": 12
          },
          "is_provisional": {
            "type": "boolean",
            "description": "True if fewer than 10 hubs contributed, or if any input data is unconfirmed. Clients should flag provisional prices appropriately.",
            "example": false
          }
        }
      },
      "PriceMessage": {
        "type": "object",
        "description": "A single $ELEC price tick. This is the primary data payload — returned by the snapshot endpoint and delivered as `price` events in the SSE stream.",
        "required": ["feed", "elec_index"],
        "properties": {
          "feed": {
            "$ref": "#/components/schemas/Feed"
          },
          "elec_index": {
            "$ref": "#/components/schemas/ElecIndex"
          }
        }
      },
      "HeartbeatMessage": {
        "type": "object",
        "description": "Sent every 30 seconds over the SSE stream to keep the connection alive and inform the client of remaining session time.",
        "required": ["timestamp", "session_expires_at"],
        "properties": {
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-01T14:05:30.0000Z"
          },
          "session_expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp when the current session token expires.",
            "example": "2026-07-01T15:00:00Z"
          }
        }
      },
      "FeedStatus": {
        "type": "object",
        "description": "Operational health of the $ELEC feed. No authentication required.",
        "properties": {
          "status": {
            "type": "string",
            "enum": ["operational", "degraded", "maintenance"],
            "description": "'degraded' means fewer than 12 hubs are contributing. 'maintenance' means the feed is temporarily offline.",
            "example": "operational"
          },
          "contracts_active": {
            "type": "integer",
            "description": "Number of hub contracts currently contributing to the index.",
            "example": 12
          },
          "contracts_total": {
            "type": "integer",
            "description": "Maximum number of hub contracts in the index.",
            "example": 12
          },
          "is_provisional": {
            "type": "boolean",
            "description": "True if the current index value is provisional.",
            "example": false
          },
          "last_tick_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of the most recently published $ELEC tick.",
            "example": "2026-07-01T14:05:00.0000Z"
          },
          "feed_version": {
            "type": "string",
            "example": "1.0"
          },
          "latency_ms": {
            "type": "integer",
            "description": "Current end-to-end latency from ICE feed to published tick, in milliseconds.",
            "example": 12
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error", "message"],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code.",
            "example": "token_expired"
          },
          "message": {
            "type": "string",
            "description": "Human-readable error description.",
            "example": "Session token has expired. Re-initiate x402 payment to obtain a new token."
          }
        }
      }
    }
  },
  "x-agent-hints": {
    "payment_protocol": "x402",
    "payment_asset": "USDC",
    "payment_network": "base-mainnet",
    "x402_library_npm": "coinbase/x402",
    "x402_library_python": "x402-python",
    "snapshot_endpoint": "/api/elec/price",
    "stream_endpoint": "/api/elec/stream",
    "status_endpoint": "/api/elec/status",
    "data_format": "USD/MWh",
    "update_frequency_ms": 500,
    "sandbox_url": "https://sandbox.elec.finance",
    "llms_txt": "https://elec.finance/llms.txt",
    "agents_json": "https://elec.finance/.well-known/agents.json"
  }
}
