Developers
Report your readers' reading to Readoactive: started, progress, finished.
Readers connect with one tap; revoke from Account. Your engineers do the rest with three calls. Ask us for a key at dydy.hadoola@gmail.com; send it on every call as Authorization: Bearer rk_… over HTTPS. Keep it on your servers, never in an app.
1. Link a reader
Send the reader's email. We answer the same whether or not they have an account (202, with a link_id); if they do, they get a note in the app and an email with an Allow button. If they sign up within 30 days, the request waits for them.
curl -X POST https://readoactive.app/api/v1/links -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"email": "hadeel@example.com"}'
# 202 {"link_id": "lk_…", "status": "pending"}
Poll the link until the reader answers. Once it is active it carries the reader_id to use from then on (it never changes, and it is all you hold: no email, no account id).
curl https://readoactive.app/api/v1/links/lk_… -H "Authorization: Bearer $KEY"
# 200 {"link_id": "lk_…", "status": "pending" | "active" | "declined" | "revoked", "reader_id": "rd_…"}
2. Report reading
One call per event: started, progress, finished or dnf (did not finish). event_id is yours and unique: a retry with the same body gets the first answer back. Unknown fields are refused, so typos show up at once.
curl -X POST https://readoactive.app/api/v1/reading/events -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"reader_id": "rd_…", "event_id": "evt-123", "event": "progress",
"at": "2026-10-22T08:30:00Z", "source": "kindle",
"book": {"title": "Fourth Wing", "author": "Rebecca Yarros", "isbn": "9781649374042", "asin": "B0BMNZ…"},
"progress": {"location": 3000, "locations": 5000}}'
# 200 {"ok": true, "work": {"id": "…", "title": "Fourth Wing", "author": "Rebecca Yarros"},
# "status": "reading", "progress_percent": 60.0, "matched_by": "isbn" | "asin" | "title" | "new"}
- book:
title,author,isbn,asin,source_id,language; at least a title, an ISBN or an ASIN. We match by ISBN, then ASIN, then title and author; a book nobody lists is added as given and matched to the catalog later. - progress:
percent, orpage/pages,location/locations,minutes/total_minutes. Progress only moves forward within one reading; send it as often as you like (pings ten minutes apart are kept as one). - at: when it happened (ISO 8601), within the last 10 years and no more than 7 days ahead.
- A
startedafter afinishedis a re-read. A book the reader marked read themselves is not undone by a late ping.
3. Read back what they are reading
curl https://readoactive.app/api/v1/readers/rd_…/reading -H "Authorization: Bearer $KEY"
# 200 {"reading": [{"title": "Fourth Wing", "author": "Rebecca Yarros", "isbn": "9781649374042",
# "progress_percent": 60.0, "started": "2026-10-20"}]}
Errors
Every error is JSON: {"error": "code", "message": "one sentence"}.
| 400 | bad_request, unknown_field, bad_time | A field is missing, unknown or out of range (`at` more than 7 days ahead or 10 years back). |
| 401 | bad_key | No key, a mistyped one, a revoked one, or one rotated more than 24 hours ago. |
| 403 | link_revoked | The reader disconnected your app. Ask them to connect again. |
| 403 | reader_not_linked | The reader has not allowed your app. |
| 404 | unknown_reader, unknown_link | No such reader id or link id for your key. |
| 409 | duplicate_event | This event_id was sent before with a different body (a retry with the same body gets the first answer). |
| 422 | unparseable_book | We could not read the book: send at least a title, an ISBN or an ASIN. |
| 429 | rate_limited | Over a limit; wait a minute. |
Limits
- 600 events a minute per key, 60 a minute per reader; every events answer carries
X-RateLimit-Remaining. - 60 link requests a minute per key, and 3 a day for one address.
- We keep a log of your calls for 90 days. We can revoke a key at any time; a rotated key keeps working for 24 hours.
Questions: dydy.hadoola@gmail.com.