1import{j as e}from"./index-CoCDGbkq.js";import{L as a}from"./vendor-react-DQyBE89E.js";import"./vendor-supabase-XJkir-Zj.js";const t=`${"https://uqzzgjjatmgjeekaxpgw.supabase.co".replace(/\/$/,"")}/functions/v1/member-api`,s=({children:o})=>e.jsx("pre",{className:"overflow-x-auto rounded-xl border border-white/10 bg-black/40 p-4 text-[12.5px] leading-relaxed text-white/85",children:e.jsx("code",{children:o})}),n=({children:o,color:l="purple"})=>{const r={green:"border-emerald-400/40 bg-emerald-500/15 text-emerald-200",amber:"border-amber-400/40 bg-amber-500/15 text-amber-200",rose:"border-rose-400/40 bg-rose-500/15 text-rose-200",purple:"border-violet-400/40 bg-violet-500/15 text-violet-200"};return e.jsx("span",{className:`inline-block rounded-md border px-2 py-0.5 text-[11px] font-bold uppercase tracking-wide ${r[l]}`,children:o})},i=({method:o,path:l,scope:r,children:d})=>{const c={GET:"green",POST:"amber",PATCH:"purple",DELETE:"rose"}[o]||"purple";return e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsxs("div",{className:"mb-2 flex flex-wrap items-center gap-2",children:[e.jsx(n,{color:c,children:o}),e.jsx("code",{className:"text-sm text-white/90",children:l}),r&&e.jsxs("span",{className:"text-[11px] text-white/40",children:["scope: ",e.jsx("code",{className:"text-white/60",children:r})]})]}),e.jsx("div",{className:"space-y-3 text-sm text-white/70",children:d})]})};function p(){return e.jsx("div",{className:"min-h-screen bg-[#0b1225] text-white",children:e.jsxs("div",{className:"mx-auto max-w-3xl px-5 py-10",children:[e.jsxs("div",{className:"mb-8",children:[e.jsx(a,{to:"/",className:"text-sm text-violet-300 hover:text-violet-200",children:"â BookMosh"}),e.jsx("h1",{className:"mt-3 text-3xl font-bold",children:"Developer API"}),e.jsx("p",{className:"mt-2 text-white/60",children:"A simple REST API over your BookMosh library. Read your books, search the catalog, and write to your own shelves. Build integrations that sync your reading from Kindle, Kobo, Apple Books, a spreadsheet, or anywhere else."})]}),e.jsxs("section",{className:"mb-10",children:[e.jsx("h2",{className:"mb-3 text-lg font-semibold text-violet-200",children:"Getting started"}),e.jsxs("ol",{className:"mb-4 list-decimal space-y-1 pl-5 text-sm text-white/70",children:[e.jsxs("li",{children:["Open ",e.jsx("span",{className:"text-white/90",children:"Profile â Settings â Developer API"})," and create an API key."]}),e.jsxs("li",{children:["Copy the key (shown once). It looks like ",e.jsx("code",{className:"text-white/80",children:"bm_live_..."}),"."]}),e.jsx("li",{children:"Send it as a Bearer token on every request."})]}),e.jsx("p",{className:"mb-2 text-xs uppercase tracking-[0.3em] text-white/40",children:"Base URL"}),e.jsx(s,{children:t}),e.jsx("p",{className:"mt-3 mb-2 text-xs uppercase tracking-[0.3em] text-white/40",children:"Authentication"}),e.jsx(s,{children:`curl "${t}/books" \\ 2 -H "Authorization: Bearer bm_live_xxx"`})]}),e.jsxs("section",{className:"mb-10 grid gap-4 sm:grid-cols-2",children:[e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsx("h3",{className:"mb-2 text-sm font-semibold text-white/90",children:"Scopes"}),e.jsxs("ul",{className:"space-y-1.5 text-sm text-white/70",children:[e.jsxs("li",{children:[e.jsx("code",{className:"text-white/85",children:"books:read"})," â read your library"]}),e.jsxs("li",{children:[e.jsx("code",{className:"text-white/85",children:"search:read"})," â search the catalog"]}),e.jsxs("li",{children:[e.jsx("code",{className:"text-white/85",children:"library:write"})," â add/update/delete your books"]})]}),e.jsxs("p",{className:"mt-2 text-[12px] text-white/45",children:["New keys include all three. Keys created before write support was added won't have ",e.jsx("code",{children:"library:write"})," â create a fresh key to get it."]})]}),e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsx("h3",{className:"mb-2 text-sm font-semibold text-white/90",children:"Rate limit"}),e.jsxs("p",{className:"text-sm text-white/70",children:["60 requests per minute, per key. Over the limit returns ",e.jsx("code",{className:"text-white/85",children:"429"})," with a ",e.jsx("code",{children:"Retry-After"})," header."]}),e.jsx("h3",{className:"mb-2 mt-4 text-sm font-semibold text-white/90",children:"Responses"}),e.jsxs("p",{className:"text-sm text-white/70",children:["JSON. Errors are ",e.jsx("code",{className:"text-white/85",children:'{ "error": "code" }'})," with an HTTP status (400, 401, 403, 404, 429, 500)."]})]})]}),e.jsxs("section",{className:"mb-10 space-y-4",children:[e.jsx("h2",{className:"text-lg font-semibold text-violet-200",children:"Endpoints"}),e.jsxs(i,{method:"GET",path:"/books",scope:"books:read",children:[e.jsx("p",{children:"List the books in your library, newest first."}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Query params: ",e.jsx("code",{children:"q"})," (title/author contains), ",e.jsx("code",{children:"status"})," (Reading, Read, To-Read, Paused, DNF), ",e.jsx("code",{children:"tag"}),", ",e.jsx("code",{children:"limit"})," (1â100, default 50), ",e.jsx("code",{children:"cursor"})," (offset from the previous ",e.jsx("code",{children:"nextCursor"}),")."]}),e.jsx(s,{children:`curl "${t}/books?status=Read&limit=20" \\ 3 -H "Authorization: Bearer bm_live_xxx" 4 5# â { "books": [ { "id": "...", "title": "...", "author": "...", 6# "status": "Read", "rating": 5, "tags": ["Read"], "isbn": "...", 7# "read_at": "...", "cover": "..." }, ... ], "nextCursor": "20" }`})]}),e.jsx(i,{method:"GET",path:"/books/{id}",scope:"books:read",children:e.jsx("p",{children:"Fetch a single book you own by its id."})}),e.jsxs(i,{method:"GET",path:"/search",scope:"search:read",children:[e.jsx("p",{children:"Search the global book catalog (not just your library)."}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Query params: ",e.jsx("code",{children:"q"})," (title/keyword) or ",e.jsx("code",{children:"isbn"}),", ",e.jsx("code",{children:"mode=author"}),", ",e.jsx("code",{children:"pageSize"})," (1â50)."]}),e.jsx(s,{children:`curl "${t}/search?q=the+hobbit" \\ 8 -H "Authorization: Bearer bm_live_xxx"`})]}),e.jsxs(i,{method:"POST",path:"/books",scope:"library:write",children:[e.jsxs("p",{children:["Add a book to ",e.jsx("span",{className:"text-white/90",children:"your own"})," library. If you already have it (matched by ISBN, else title), the existing entry is updated instead of duplicated."]}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Body: ",e.jsx("code",{children:"title"})," and ",e.jsx("code",{children:"author"})," are required. Optional: ",e.jsx("code",{children:"isbn"}),", ",e.jsx("code",{children:"status"}),", ",e.jsx("code",{children:"rating"})," (0â5), ",e.jsx("code",{children:"tags"})," (array), ",e.jsx("code",{children:"cover"}),", ",e.jsx("code",{children:"pages"}),", ",e.jsx("code",{children:"year"}),", ",e.jsx("code",{children:"read_at"}),"."]}),e.jsx("p",{className:"text-[13px] text-white/55",children:"If the book has a valid ISBN and isn't in our
8catalog yet, it's validated and added to the shared catalog (add-only, never overwriting) so everyone benefits. Books without an ISBN are still saved to your library, they just don't touch the shared catalog."}),e.jsx(s,{children:`curl -X POST "${t}/books" \\ 9 -H "Authorization: Bearer bm_live_xxx" \\ 10 -H "Content-Type: application/json" \\ 11 -d '{ 12 "title": "The Left Hand of Darkness", 13 "author": "Ursula K. Le Guin", 14 "isbn": "9780441478125", 15 "status": "Read", 16 "rating": 5 17 }' 18 19# â { "book": { "id": "...", ... }, "created": true }`})]}),e.jsxs(i,{method:"PATCH",path:"/books/{id}",scope:"library:write",children:[e.jsx("p",{children:"Update one of your books. Send only the fields you want to change."}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Updatable: ",e.jsx("code",{children:"status"}),", ",e.jsx("code",{children:"rating"}),", ",e.jsx("code",{children:"progress"})," (0â100), ",e.jsx("code",{children:"current_page"}),", ",e.jsx("code",{children:"read_at"}),", ",e.jsx("code",{children:"tags"}),", ",e.jsx("code",{children:"cover"}),"."]}),e.jsx(s,{children:`curl -X PATCH "${t}/books/BOOK_ID" \\ 20 -H "Authorization: Bearer bm_live_xxx" \\ 21 -H "Content-Type: application/json" \\ 22 -d '{ "status": "Read", "rating": 4 }'`})]}),e.jsxs(i,{method:"DELETE",path:"/books/{id}",scope:"library:write",children:[e.jsx("p",{children:"Remove one of your books."}),e.jsx(s,{children:`curl -X DELETE "${t}/books/BOOK_ID" \\ 23 -H "Authorization: Bearer bm_live_xxx" 24# â { "deleted": true, "id": "BOOK_ID" }`})]}),e.jsxs("div",{className:"pt-2",children:[e.jsx("h3",{className:"mb-1 text-sm font-semibold text-white/90",children:"Lists (collections)"}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Reading lists are collections of books, each ",e.jsx("span",{className:"text-white/80",children:"public"})," or ",e.jsx("span",{className:"text-white/80",children:"private"}),". Reads return your own lists, plus anyone's public list by id. Writes only ever touch your own lists."]})]}),e.jsxs(i,{method:"GET",path:"/lists",scope:"books:read",children:[e.jsx("p",{children:"List your own reading lists, newest first."}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Query params: ",e.jsx("code",{children:"limit"})," (1â100, default 50), ",e.jsx("code",{children:"cursor"}),"."]}),e.jsx(s,{children:`curl "${t}/lists" \\ 25 -H "Authorization: Bearer bm_live_xxx" 26 27# â { "lists": [ { "id": "...", "title": "Summer 2026", 28# "description": "...", "is_public": true, 29# "owner_username": "you", "created_at": "...", 30# "updated_at": "..." }, ... ], "nextCursor": null }`})]}),e.jsxs(i,{method:"GET",path:"/lists/{id}",scope:"books:read",children:[e.jsxs("p",{children:["Fetch one list and its books. Returns your own list, or anyone's ",e.jsx("span",{className:"text-white/90",children:"public"})," list; a private list you don't own returns ",e.jsx("code",{children:"404"}),"."]}),e.jsx(s,{children:`curl "${t}/lists/LIST_ID" \\ 31 -H "Authorization: Bearer bm_live_xxx" 32 33# â { "list": { "id": "...", "title": "...", "is_public": true, 34# "is_owner": true, ... }, 35# "items": [ { "id": "...", "book_title": "...", 36# "book_author": "...", "isbn": "...", 37# "book_cover": "...", "position": 0 }, ... ] }`})]}),e.jsxs(i,{method:"POST",path:"/lists",scope:"library:write",children:[e.jsxs("p",{children:["Create a new list. ",e.jsx("code",{children:"title"})," is required. It's ",e.jsx("span",{className:"text-white/90",children:"private by default"}),"; pass ",e.jsx("code",{children:"is_public: true"})," (or ",e.jsx("code",{children:'visibility: "public"'}),") to make it shareable by link."]}),e.jsxs("p",{className:"text-[13px] text-white/55",children:["Optional: ",e.jsx("code",{children:"description"}),", and a ",e.jsx("code",{children:"books"})," array to seed it in the same call (each book needs a ",e.jsx("code",{children:"title"}),"; ",e.jsx("code",{children:"author"}),", ",e.jsx("code",{children:"isbn"}),", ",e.jsx("code",{children:"cover"})," optional)."]}),e.jsx(s,{children:`curl -X POST "${t}/lists" \\ 38 -H "Authorization: Bearer bm_live_xxx" \\ 39 -H "Content-Type: application/json" \\ 40 -d '{ 41 "title": "Best sci-fi of the decade", 42 "description": "A running favorites list", 43 "is_public": true, 44 "books": [ 45 { "title": "The Left Hand of Darkness", 46 "author": "Ursula K. Le Guin", 47 "isbn": "9780441478125" } 48 ] 49 }' 50 51# â { "list": { "id": "...", ... }, "items": [ ... ], "created": true }`})]}),e.jsxs(i,{method:"PATCH",path:"/lists/{id}",scope:"library:write",children:[e.jsxs("p",{children:["Update one of your lists. Send only what changes. Toggle ",e.jsx("code",{children:"is_public"})," (or ",e.jsx("code",{children:"visibility"}),") to make a list public or private."]}),e.jsx(s,{children:`curl -X PATCH "${t}/lists/LIST_ID" \\ 52 -H "Authorization: Bearer bm_live_xxx" \\ 53 -H "Content-Type: application/json" \\ 54 -d '{ "title": "Renamed list", "is_public": false }'`})]}),e.jsxs(i,{method:"DELETE",path:"/lists/{id}",scope:"library:write",children:[e.jsx("p",{children:"Delete one of your lists and all of its books."}),e.jsx(s,{children:`curl -X DELETE "${t}/lists/LIST_ID" \\ 55 -H "Authorization: Bearer bm_live_xxx" 56# â { "deleted": true, "id": "LIST_ID" }`})]}),e.jsxs(i,{method:"POST",path:"/lists/{id}/books",scope:"library:write",children:[e.jsxs("p",{children:["Add a book to one of your lists. ",e.jsx("code",{children:"title"})," is required. Duplicates (matched by ISBN, else title and author) are skipped."]}),e.jsx(s,{children:`curl -X POST "${t}/lists/LIST_ID/books" \\ 57 -H "Authorization: Bearer bm_live_xxx" \\ 58 -H "Content-Type: application/json" \\ 59 -d '{ "title": "Dune", "author": "Frank Herbert", 60 "isbn": "9780441013593" }' 61 62# â { "item": { "id": "...", ... }, "added": true }`})]}),e.jsxs(i,{method:"DELETE",path:"/lists/{id}/books/{itemId}",scope:"library:write",children:[e.jsxs("p",{children:["Remove a book from one of your lists. The ",e.jsx("code",{children:"itemId"})," is a list item id from ",e.jsx("code",{children:"GET /lists/{id}"}),"."]}),e.jsx(s,{children:`curl -X DELETE "${t}/lists/LIST_ID/books/ITEM_ID" \\ 63 -H "Authorization: Bearer bm_live_xxx" 64# â { "deleted": true, "id": "ITEM_ID" }`})]})]}),e.jsxs("section",{className:"mb-10",children:[e.jsx("h2",{className:"mb-3 text-lg font-semibold text-violet-200",children:"What you can build"}),e.jsx("p",{className:"mb-4 text-sm text-white/60",children:"All of these are possible with the endpoints above today."}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsx("h3",{className:"text-sm font-semibold text-white/90",children:"Sync your Kindle / Kobo / Apple Books reading"}),e.jsxs("p",{className:"mt-1 text-[13px] text-white/60",children:["Export your reading history from the other app, then ",e.jsx("code",{children:"POST /books"})," each finished title with ",e.jsx("code",{children:'status: "Read"'})," and a ",e.jsx("code",{children:"read_at"})," date. Genuinely-new books with an ISBN get added to the catalog automatically, so covers and details fill in."]}),e.jsx(s,{children:`# pseudo-code: push a finished Kindle book into BookMosh 65for book in kindle_export: 66 POST /books { title, author, isbn: book.asin_isbn, 67 status: "Read", read_at: book.finished_date }`})]}),e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsx("h3",{className:"text-sm font-semibold text-white/90",children:"Nightly backup / export to a spreadsheet"}),e.jsxs("p",{className:"mt-1 text-[13px] text-white/60",children:["Page through ",e.jsx("code",{children:"GET /books"})," with ",e.jsx("code",{children:"cursor"})," and write the rows to CSV, Google Sheets, Notion, or your own database."]})]}),e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsx("h3",{className:"text-sm font-semibold text-white/90",children:"Auto-log a book when you finish it elsewhere"}),e.jsxs("p",{className:"mt-1 text-[13px] text-white/60",children:["Wire a shortcut, a webhook, or a smart-home automation to ",e.jsx("code",{children:"POST /books"})," (or ",e.jsx("code",{children:"PATCH"})," an existing one to ",e.jsx("code",{children:'status: "Read"'}),") the moment you finish a book in another service."]})]}),e.jsxs("div",{className:"rounded-2xl border border-white/10 bg-white/[0.03] p-5",children:[e.jsx("h3",{className:"text-sm font-semibold text-white/90",children:"A custom reading dashboard or widget"}),e.jsxs("p",{className:"mt-1 text-[13px] text-white/60",children:["Pull your currently-reading and finished counts with ",e.jsx("code",{children:"GET /books?
67status=Reading"})," and ",e.jsx("code",{children:"?status=Read"})," to power a personal stats page, a Raycast/Alfred command, or a desk display."]})]})]})]}),e.jsxs("section",{className:"mb-10",children:[e.jsx("h2",{className:"mb-3 text-lg font-semibold text-violet-200",children:"Connect to Claude (MCP)"}),e.jsxs("p",{className:"mb-4 text-sm text-white/60",children:["BookMosh ships a ",e.jsx("a",{href:"https://modelcontextprotocol.io",target:"_blank",rel:"noopener noreferrer",className:"text-violet-300 hover:text-violet-200",children:"Model Context Protocol"})," server, so you can plug your reading library straight into Claude and other AI tools. Ask in plain language: ",e.jsx("span",{className:"text-white/80",children:"âadd The Left Hand of Darkness to my to-read shelfâ"})," or ",e.jsx("span",{className:"text-white/80",children:"âwhat am I currently reading?â"})]}),e.jsxs("div",{className:"mb-4",children:[e.jsx("h3",{className:"mb-2 text-sm font-semibold text-white/90",children:"Claude Desktop"}),e.jsxs("p",{className:"mb-2 text-[13px] text-white/60",children:["Add this to ",e.jsx("code",{children:"claude_desktop_config.json"})," (Settings â Developer â Edit Config), then restart."]}),e.jsx(s,{children:`{ 68 "mcpServers": { 69 "bookmosh": { 70 "command": "npx", 71 "args": ["-y", "bookmosh-mcp"], 72 "env": { "BOOKMOSH_API_KEY": "bm_live_xxx" } 73 } 74 } 75}`})]}),e.jsxs("div",{className:"mb-4",children:[e.jsx("h3",{className:"mb-2 text-sm font-semibold text-white/90",children:"Claude Code"}),e.jsx(s,{children:`claude mcp add bookmosh \\ 76 --env BOOKMOSH_API_KEY=bm_live_xxx \\ 77 -- npx -y bookmosh-mcp`})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"mb-2 text-sm font-semibold text-white/90",children:"Tools it exposes"}),e.jsxs("ul",{className:"list-disc space-y-1 pl-5 text-[13px] text-white/60",children:[e.jsxs("li",{children:[e.jsx("code",{children:"search_catalog"}),": search 380,000+ books by title, author, or ISBN."]}),e.jsxs("li",{children:[e.jsx("code",{children:"list_my_books"})," / ",e.jsx("code",{children:"get_my_book"}),": read your shelves."]}),e.jsxs("li",{children:[e.jsx("code",{children:"add_book"})," / ",e.jsx("code",{children:"update_book"})," / ",e.jsx("code",{children:"remove_book"}),": manage your library."]}),e.jsxs("li",{children:[e.jsx("code",{children:"list_my_lists"})," / ",e.jsx("code",{children:"get_list"}),": read your lists (and anyone's public list)."]}),e.jsxs("li",{children:[e.jsx("code",{children:"create_list"})," / ",e.jsx("code",{children:"update_list"})," / ",e.jsx("code",{children:"delete_list"}),": manage lists, public or private."]}),e.jsxs("li",{children:[e.jsx("code",{children:"add_book_to_list"})," / ",e.jsx("code",{children:"remove_book_from_list"}),": curate a list's books."]})]}),e.jsxs("p",{className:"mt-3 text-[13px] text-white/50",children:["Uses the same ",e.jsx("code",{children:"bm_live_"})," key as the REST API. It only ever accesses your own library and lists (plus public lists you look up by id)."]})]})]}),e.jsxs("section",{className:"mb-10",children:[e.jsx("h2",{className:"mb-3 text-lg font-semibold text-violet-200",children:"Notes & limits"}),e.jsxs("ul",{className:"list-disc space-y-1.5 pl-5 text-sm text-white/65",children:[e.jsxs("li",{children:["Writes only ever touch ",e.jsx("span",{className:"text-white/85",children:"your own"})," library. A key cannot read or modify anyone else's books."]}),e.jsx("li",{children:"The API never edits the shared catalog's existing entries; it only adds genuinely-new, validated books."}),e.jsx("li",{children:"Keep your key secret. Anyone with it can read and write your library. Revoke and rotate keys from Settings anytime."}),e.jsx("li",{children:"This is v1 and may evolve. Building something? We'd love to hear about it."})]})]}),e.jsx("div",{className:"border-t border-white/10 pt-6 text-sm text-white/40",children:e.jsx(a,{to:"/",className:"text-violet-300 hover:text-violet-200",children:"Back to BookMosh"})})]})})}export{p as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.