{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Resumly API — test drive\n",
    "\n",
    "Run this against your own account to verify the API end to end.\n",
    "\n",
    "**Cells 1–6 are FREE** (reads cost nothing). **Cell 7 onwards costs money** and is\n",
    "commented out — uncomment deliberately.\n",
    "\n",
    "Get a key: [app.resumly.ai](https://app.resumly.ai) → **Settings → API → New Key**.\n",
    "Your first key includes **$5 of free credit**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install --quiet --upgrade resumly"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from resumly import Resumly\n",
    "\n",
    "API_KEY = \"rly_PASTE_YOUR_KEY_HERE\"   # <-- shown once at creation\n",
    "\n",
    "resumly = Resumly(api_key=API_KEY)\n",
    "print(\"client ready ->\", resumly._base_url)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 · Balance — proves your key works (FREE)\n",
    "\n",
    "This is also your spend cap: metered calls stop with a 402 at $0.00."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wallet = resumly.balance()\n",
    "print(f\"balance          ${wallet['balance_usd']:.2f}\")\n",
    "print(f\"trial credit     {wallet['trial_credit_granted']}\")\n",
    "print(f\"lifetime spend   ${wallet['lifetime_spend_usd']:.2f}\")\n",
    "print(\"\\nprice card:\")\n",
    "for op, price in sorted(wallet[\"prices_usd\"].items(), key=lambda kv: kv[1]):\n",
    "    print(f\"  ${price:<6.2f} {op}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 · Your saved searches (FREE)\n",
    "\n",
    "`last_refreshed_at` is what tells you whether a $0.05 refresh is worth it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "searches = resumly.queries()[\"queries\"]\n",
    "print(f\"{len(searches)} saved search(es)\\n\")\n",
    "for s in searches:\n",
    "    print(f\"  {s.get('query_name')}\")\n",
    "    print(f\"    id             {s.get('_id')}\")\n",
    "    print(f\"    last refreshed {s.get('last_refreshed_at')}\")\n",
    "    print(f\"    new last run   {s.get('new_jobs_last_run')}\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 · Your matched-jobs board (FREE)\n",
    "\n",
    "The same rows the web app shows — scores, salary, appliability."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "board = resumly.jobs(page_size=10, sort_by=\"match\")\n",
    "print(f\"{board['total_count']} matched jobs\\n\")\n",
    "for job in board[\"result\"]:\n",
    "    score = job.get(\"match_score_extended\")\n",
    "    pct = f\"{score:.0%}\" if isinstance(score, (int, float)) else \" n/a\"\n",
    "    apply_ok = \"auto-apply\" if job.get(\"auto_apply\") else \"          \"\n",
    "    print(f\"  {pct}  {apply_ok}  {job.get('title')}  @ {job.get('organization')}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Full detail for the top match (FREE) — description, url, score insight\n",
    "if board[\"result\"]:\n",
    "    top = board[\"result\"][0]\n",
    "    detail = resumly.job(top[\"_id\"])\n",
    "    print(detail.get(\"title\"), \"@\", detail.get(\"organization\"))\n",
    "    print(\"url:\", detail.get(\"url\"))\n",
    "    print(\"skills matched:\", detail.get(\"match_score_v2_skills_matched\"))\n",
    "    print(\"skills missing:\", detail.get(\"match_score_v2_skills_missing\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4 · Applications and employer replies (FREE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "apps = resumly.applications(status=\"applied\")\n",
    "print(f\"applied: {apps.get('total_count')}\")\n",
    "\n",
    "interviews = resumly.applications(status=\"interview\")\n",
    "print(f\"interview stage: {interviews.get('total_count')}\")\n",
    "for job in interviews.get(\"result\", [])[:5]:\n",
    "    print(f\"  {job.get('title')} @ {job.get('organization')}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Classified employer email (FREE) — interview_invitation | offer | rejection | ...\n",
    "inbox = resumly.inbox_emails(category=\"interview_invitation\", page=1)\n",
    "emails = inbox.get(\"emails\", inbox.get(\"result\", []))\n",
    "print(f\"{len(emails)} interview invitation(s)\")\n",
    "for e in emails[:5]:\n",
    "    print(\"  -\", e.get(\"subject\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5 · Usage ledger (FREE) — every charge, itemized"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "usage = resumly.usage(page_size=20)\n",
    "print(f\"{usage['total']} ledger row(s)\")\n",
    "for row in usage[\"usage\"]:\n",
    "    print(f\"  {row['created_at'][:19]}  {row['operation']:<24} \"\n",
    "          f\"${row['amount_usd']:>6.2f}  {row['status']}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6 · Long-running work (FREE to track)\n",
    "\n",
    "Tailoring, applying, refreshing a search and PDF export return `202` with an `operation_id` — they cannot finish inside one HTTP request. Poll one endpoint for all of them:\n",
    "\n",
    "```python\n",
    "done = resumly.wait(op[\"operation_id\"], timeout=300)\n",
    "```\n",
    "\n",
    "`status` is `queued` → `running` → `succeeded` | `failed` | `needs_attention`.\n",
    "\n",
    "`needs_attention` means an application a human must finish — not a failure, and your money stays reserved.\n",
    "\n",
    "```python\n",
    "resumly.operations(page_size=5)   # recent operations, free\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "# 💸 Everything below costs money\n",
    "\n",
    "Each cell is commented out. Uncomment only what you want to pay for.\n",
    "Failures are never billed, and your balance is a hard cap."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## $0.05 — refresh a saved search (new jobs land already scored)\n",
    "# before = resumly.balance()[\"balance_usd\"]\n",
    "# result = resumly.refresh(searches[0][\"_id\"])\n",
    "# print(result)\n",
    "# print(f\"balance ${before:.2f} -> ${resumly.balance()['balance_usd']:.2f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## $0.25 — tailor your resume for the top match\n",
    "## Tailoring is ASYNC: the call returns immediately with an operation_id.\n",
    "# queued = resumly.tailor(job_id=board[\"result\"][0][\"_id\"])\n",
    "# print(queued)\n",
    "\n",
    "## One wait loop covers tailoring, applying, refreshing and exports.\n",
    "## Polling is free.\n",
    "# done = resumly.wait(queued[\"operation_id\"], timeout=300)\n",
    "# print(done[\"status\"])            # succeeded\n",
    "# resume_id = done[\"result\"][\"resume_id\"]\n",
    "\n",
    "## then download the DOCX (FREE)\n",
    "# resumly.download(resume_id, path=\"tailored_resume.docx\")\n",
    "# print(\"saved tailored_resume.docx\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## $0.10 — cover letter for that tailored resume\n",
    "# print(resumly.cover_letter(resume_id))\n",
    "\n",
    "## $0.25 — company research (interview prep)\n",
    "# print(resumly.company_research(board[\"result\"][0][\"_id\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "## $0.50 — submit a REAL application (billed only if it lands)\n",
    "## Two steps on purpose: quote, then execute.\n",
    "# job_id = board[\"result\"][0][\"_id\"]\n",
    "# queued = resumly.apply(job_id, resume_id)\n",
    "# print(queued)\n",
    "\n",
    "## Applications take MINUTES — a worker drives a real ATS.\n",
    "# final = resumly.wait(queued[\"operation_id\"], timeout=900)\n",
    "# print(final[\"status\"])\n",
    "\n",
    "## needs_attention is NOT a failure: a human is finishing it and the\n",
    "## $0.50 stays reserved until it resolves.\n",
    "# if final[\"status\"] == \"needs_attention\":\n",
    "#     print(final[\"error\"][\"message\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## Top up when you run out\n",
    "\n",
    "```python\n",
    "print(resumly.buy_credit(\"25\"))   # returns a Stripe checkout URL to open\n",
    "```\n",
    "\n",
    "Prefer chat over code? Connect the same account to Cursor or Claude Code:\n",
    "[resumly.ai/docs/mcp](https://www.resumly.ai/docs/mcp)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}