Examples
Available onProResearch
Four small examples that use real routes. They use curl and Node 18 or newer, which has fetch
built in, and no packages. Each one says which scopes the key needs, so create a key with only
those. See Authentication and API keys.
Set your key once in the shell:
export READSIRA_KEY="pk_..."
Save a link
Scopes: read:collections, write:bookmarks.
A bookmark needs a title and the collectionId of the collection it goes in. First list your
collections and pick one:
curl "https://api.readsira.com/api/v1/collections" \
-H "Authorization: Bearer $READSIRA_KEY"
The answer has your collections in data. Copy the id of one, then save the link:
curl -X POST "https://api.readsira.com/api/v1/bookmarks" \
-H "Authorization: Bearer $READSIRA_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/grid-lab",
"title": "Grid Lab: long-duration storage",
"collectionId": "PUT-A-COLLECTION-ID-HERE",
"tags": ["energy"]
}'
The answer has the new bookmark in data, including its id. tags is optional, with up to 20
tags. Saving a link counts as a request against your daily limit.
Read the highlights of a saved item
Scope: read:library.
Search finds the item and gives its documentId. Reading the document returns your highlights,
tags and notes next to the text.
const headers = { Authorization: `Bearer ${process.env.READSIRA_KEY}` };
const search = await fetch(
'https://api.readsira.com/rest/v2/search?' + new URLSearchParams({ q: 'long-duration storage', limit: '1' }),
{ headers },
).then((r) => r.json());
const hit = search.data.results[0];
if (!hit) throw new Error('Nothing found');
const doc = await fetch(
`https://api.readsira.com/rest/v2/documents/${hit.documentId}?maxChars=1`,
{ headers },
).then((r) => r.json());
console.log(doc.data.title);
for (const h of doc.data.highlights) console.log('-', h.text, h.note ? `(${h.note})` : '');
maxChars=1 asks for one character of text, because here you only want the highlights. Highlights
come with every answer. To read the whole text, see Pagination.
Ask a question with citations
Scope: ask:library. This uses your AI budget and counts toward the answers you get each month.
curl -X POST "https://api.readsira.com/rest/v2/ask" \
-H "Authorization: Bearer $READSIRA_KEY" \
-H "Content-Type: application/json" \
-d '{ "question": "What did I save about iron-air batteries?" }'
The answer in data has answer, with markers such as [1], and citations. Marker [n] points to
citations[n-1], which has the title, url and the quote it is based on. verified is true
when the quote was found in the cited passage.
Sync your library to a file
Scope: read:bookmarks.
This script reads every bookmark, a page at a time, and writes them to readsira-library.json. It
waits when the API says to slow down. Run it with node sync.mjs.
import { writeFile } from 'node:fs/promises';
const BASE = 'https://api.readsira.com';
const headers = { Authorization: `Bearer ${process.env.READSIRA_KEY}` };
async function get(path) {
for (;;) {
const res = await fetch(BASE + path, { headers });
if (res.status === 429) {
const wait = Number(res.headers.get('retry-after') ?? 60);
console.log(`Rate limited, waiting ${wait} seconds`);
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
continue;
}
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
return (await res.json()).data;
}
}
const bookmarks = [];
for (let page = 1; ; page++) {
const data = await get(`/api/v1/bookmarks?page=${page}&limit=100`);
bookmarks.push(...data.bookmarks);
console.log(`Page ${page}: ${bookmarks.length} of ${data.total}`);
if (!data.hasMore) break;
}
await writeFile('readsira-library.json', JSON.stringify(bookmarks, null, 2));
console.log(`Wrote ${bookmarks.length} bookmarks`);
Each run reads the whole library, so run it as often as you need and no more. For a copy of everything including notes and highlights in one file, use the export in Privacy and your data.
Tips
- Check a route in the reference before you build on it.
- Handle
429as in the sync script, and stop on other errors. See Rate limits and errors. - Keep keys out of scripts you share. Read them from the environment.