{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Five PrizePicks props in Python\n",
        "Independent developer service. Run without a key for fictional demo records. Set PRIZEPICKS_API_KEY outside the notebook for authenticated reads. No credentials or output are saved here. Task summaries are retained for 35 days."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import json\n",
        "import os\n",
        "import time\n",
        "from urllib.error import HTTPError, URLError\n",
        "from urllib.parse import urlencode\n",
        "from urllib.request import Request, urlopen\n",
        "\n",
        "API_KEY = os.environ.get(\"PRIZEPICKS_API_KEY\")\n",
        "BASE = \"https://prizepicksapi.com\"\n",
        "PATH = \"/api/v1/projections\" if API_KEY else \"/api/v1/demo/projections\"\n",
        "HEADERS = {\"Accept\": \"application/json\"}\n",
        "if API_KEY:\n",
        "    HEADERS[\"Authorization\"] = \"Bearer \" + API_KEY\n",
        "    HEADERS[\"X-User-Request\"] = \"Read five NBA props for an integration check\"\n",
        "\n",
        "\n",
        "def projections(league=\"NBA\", stat=None, max_pages=1):\n",
        "    cursor = None\n",
        "    seen_cursors = set()\n",
        "    for page_number in range(max_pages):\n",
        "        params = {\"league\": league, \"limit\": 5}\n",
        "        if stat:\n",
        "            params[\"stat\"] = stat\n",
        "        if cursor:\n",
        "            params[\"cursor\"] = cursor\n",
        "        request = Request(BASE + PATH + \"?\" + urlencode(params), headers=HEADERS)\n",
        "        try:\n",
        "            with urlopen(request, timeout=20) as response:\n",
        "                page = json.load(response)\n",
        "        except HTTPError as error:\n",
        "            detail = error.read().decode(\"utf-8\", errors=\"replace\")\n",
        "            raise RuntimeError(f\"HTTP {error.code}: {detail}\") from None\n",
        "        except URLError as error:\n",
        "            raise RuntimeError(f\"Request failed: {error.reason}\") from None\n",
        "\n",
        "        meta = page[\"meta\"]\n",
        "        print(\"Source:\", meta[\"source_status\"], \"Observed:\", meta[\"observed_at\"])\n",
        "        for projection in page[\"data\"]:\n",
        "            if API_KEY and projection.get(\"is_demo\"):\n",
        "                raise RuntimeError(\"Unexpected demo record in live response\")\n",
        "            yield projection\n",
        "\n",
        "        cursor = meta.get(\"next_cursor\")\n",
        "        if not cursor:\n",
        "            return\n",
        "        if cursor in seen_cursors:\n",
        "            raise RuntimeError(\"Repeated pagination cursor\")\n",
        "        seen_cursors.add(cursor)\n",
        "        if page_number + 1 == max_pages:\n",
        "            print(\"Partial board: more rows are available; increase max_pages deliberately.\")\n",
        "            return\n",
        "        time.sleep(1.1)  # Pace serial page requests below the Free minute limit.\n",
        "\n",
        "\n",
        "if __name__ == \"__main__\":\n",
        "    print(\"Mode:\", \"authenticated observations\" if API_KEY else \"fictional demo\")\n",
        "    for item in projections():\n",
        "        print(item[\"id\"], item[\"player\"][\"name\"], item[\"market\"][\"stat\"], item[\"line\"])\n"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
