Skip to content
sponge
Start your library
Theme
Appearance

Migration

Move a Readwise Reader library to Sponge

List every saved document with the Reader API, then save each link to Sponge with a short script and re-create the highlights that still match.

Drafted with AI from the source code and reviewed by Claude Opus 5.5 (claude-opus-5-5) editorial review.

There is no one-click Reader importer in Sponge. The move is a scripted loop over the Reader API: page through your documents, save each link through Sponge’s library command, then re-create the highlights and notes that still match the saved copy. Every step below uses documented public endpoints on both sides.

Get tokens for both services

  1. Get your Reader access token at readwise.io/access_token.
  2. Sign in to Sponge, open /settings/api, and create a token with library:write. Add library:read if you want the same credential to check results. Keep the token in SPONGE_API_TOKEN and never print it. Every response’s X-Sponge-Requests-Remaining header shows what is left of the token’s request budget.
  3. Set up a working directory for the export, with one JSON file per list page and a log of what your loop has already saved.

Export your Reader documents

GET https://readwise.io/api/v3/list/ returns your library in pages. Pass Authorization: Token <your token>, follow nextPageCursor until it is null, and keep each result’s id, source_url, category, location, and notes. The endpoint allows 20 requests per minute; on a 429, wait out the Retry-After header.

  • Limit the loop to the categories Sponge can keep: article, pdf, and web pages saved as other types. EPUBs, tweets, videos, emails, and RSS items have no Sponge equivalent.
  • If you uploaded files, add withRawSourceUrl to list calls. Each result then includes a direct link to the stored file that expires after one hour, so download those files as you go.
  • Reader stores highlights and notes as documents too. Entries with category=highlight carry parent_id (the article they belong to), content (the passage), and notes (your note). List them now and save the JSON.

For every exported source_url, send Sponge’s save-link command once. Give each save a stable idempotencyKey of 16 or more characters, such as readwise-<document id>, so a retried request returns the same item instead of a duplicate.

curl -X POST https://sponge.computer/api/v1/library \
  -H "Authorization: Bearer $SPONGE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":"save-link","url":"https://example.org/field-study","idempotencyKey":"readwise-01abc123"}'

The command stores the save immediately and prepares the capture in the background. Read the item back with list or get to see when its copy is ready. If a page cannot be fetched, Sponge keeps the item and marks the capture as failed or partial. An agent running the Sponge CLI can do the same through the sponge_library_save_link MCP tool with a requestKey per save.

Sponge fetches the page when you save it; it does not copy Reader’s stored version. A page that changed since Reader saved it arrives as it is now, and a page that needs a sign-in does not come over at all.

Re-create your highlights and notes

A Sponge highlight anchors to the saved copy’s text: each selection carries the passage, its start and end offsets, and the context on each side. To carry a Reader highlight over:

  1. Read the saved item’s text with the reader-page command, which returns the capture and representation identifiers a selection needs.
  2. Find the Reader highlight’s content in that text and build the selection: exact holds the passage, start and end its offsets, prefix and suffix the context on each side, plus the capture, representation, and block identifiers from step one.
  3. Send {"type":"highlight","sourceId":…,"selections":[…],"idempotencyKey":…} with a stable key per highlight. Sponge refuses a selection that does not match the saved text.

If Reader’s stored page differs from what Sponge captured, some passages will not be found; those highlights stay in your export as records rather than anchored marks. A Reader note that is not a highlight becomes a create-note item on the same source.

Carry over reading state, files, and tags

  • Reader’s archive location becomes Sponge’s archived state and seen becomes read: send set-reading-state with the item’s current expectedRevision plus read and archived.
  • shortlist and feed have no Sponge equivalent; decide for yourself whether to file those items as unread or archived.
  • Tags do not transfer, because Sponge has no tags. It keeps sources, highlights, and notes.
  • Downloaded PDFs and saved HTML files can be uploaded through Sponge’s file upload (prepare-upload, then finish-upload); EPUBs are not a supported file type.
  • Sponge’s API has an import command, prepare-import, but it works only with a migration plan Sponge has set up for you, so you cannot use it on your own today. Use the loop above instead.

Rerun the loop to finish failed saves

Keep the Reader export and your run log together, with a record of which document IDs saved, which are waiting on capture, and which failed. Then run the same loop again with the same keys. Finished saves return the same items, so only the missing or failed entries move.