Skip to main content

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_..."

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 429 as 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.