# Integrating BookLink.fyi

BookLink.fyi gives every book one link that shows every place to get it: new,
used, ebook, audiobook, libraries, and free public-domain sources. You can send
your readers to it with a plain link, or look books up through a small JSON API.
It is free, and the basics need no account or API key.

This page is also available as plain markdown at
[/developers.md](https://booklink.fyi/developers.md), and there is a short index
for AI agents at [/llms.txt](https://booklink.fyi/llms.txt).

## The 60-second integration: one link

If you have the book's ISBN, this is the whole integration:

```html
<a href="https://booklink.fyi/isbn/9780593983768" target="_blank" rel="noopener">
  More stores &amp; libraries
</a>
```

`/isbn/{isbn}` accepts ISBN-10 or ISBN-13, with or without hyphens, and
redirects to the book's page. If we have never seen the book, the first person
to click creates it; it takes a second or two.

The page you land on describes the edition that ISBN belongs to. If you hold
several ISBNs for a book, send the mainstream trade edition (the ordinary
hardcover or paperback) rather than a large-print, library-binding, audiobook or
translated edition.

No ISBN? Link to a search instead. When we are confident about the match the
reader lands directly on the book; otherwise they see results to pick from.

```
https://booklink.fyi/search?q=There+Is+No+Antimemetics+Division+qntm
```

Already have a retailer link (Amazon, Bookshop.org, Barnes & Noble, Goodreads,
Kobo, Apple Books, and more)? Hand it to us and we will work out the book:

```
https://booklink.fyi/resolve?url=https%3A%2F%2Fbookshop.org%2Fa%2F114321%2F9780593983768
```

In React:

```jsx
function BookLinkButton({ isbn, title, author }) {
  const href = isbn
    ? `https://booklink.fyi/isbn/${isbn}`
    : `https://booklink.fyi/search?q=${encodeURIComponent(`${title} ${author ?? ""}`.trim())}`;
  return (
    <a href={href} target="_blank" rel="noopener">
      More options on BookLink.fyi
    </a>
  );
}
```

### URL reference

| URL | What it does |
|---|---|
| `/isbn/{isbn}` | Redirects to the book's page. 404 page if the ISBN is unknown to every source. |
| `/search?q={text}` | Goes straight to the book on a confident match, else shows results. |
| `/resolve?url={retailer-url}` | Redirects to the book, else to a search, else home. |
| `/book/{slug}` | The canonical book page. Stable; safe to store. |
| `/b/{slug}` | Short form of the same page. |

## JSON API

Base URL `https://booklink.fyi/api/v1`. Responses are JSON. CORS is open
(`Access-Control-Allow-Origin: *`), so browser-side calls work.

- **Auth:** none required. An optional `X-API-Key` header raises your rate limit.
  Keys are issued by hand for now: write to hello@booklink.fyi.
- **Rate limits:** 20 requests/minute per IP without a key, 120/minute with one.
  Over the limit returns `429`.
- **`source` parameter:** always send `source=app-{yourname}` so we can tell your
  traffic apart and get in touch before changing anything you depend on.
- **Machine-readable schema:** [/openapi.json](https://booklink.fyi/openapi.json)
  (human view at [/docs](https://booklink.fyi/docs)).

### `GET /api/v1/resolve` — retailer URL to book

```
curl "https://booklink.fyi/api/v1/resolve?source=app-example&url=https%3A%2F%2Fbookshop.org%2Fa%2F114321%2F9780593983768"
```

```json
{
  "status": "found",
  "booklink_url": "https://booklink.fyi/book/there-is-no-antimemetics-division-qntm",
  "short_url": "https://booklink.fyi/b/there-is-no-antimemetics-division-qntm",
  "title": "There Is No Antimemetics Division",
  "authors": ["qntm"],
  "cover_url": "https://…",
  "isbn": "9780593983768"
}
```

When the URL cannot be pinned to one book you get `"status": "not_found"` with a
`search_url` you can send the reader to instead.

### `GET /api/v1/search` — text to candidate books

Parameters: `q` (required, up to 500 characters), `limit` (1–20, default 5).

```
curl "https://booklink.fyi/api/v1/search?source=app-example&q=piranesi&limit=3"
```

```json
{
  "status": "found",
  "results": [
    {
      "title": "Piranesi",
      "authors": ["Susanna Clarke"],
      "cover_url": "https://…",
      "isbn": "9781635575637",
      "published_date": "2020-09-15",
      "search_url": "https://booklink.fyi/search?q=piranesi&pick=0"
    }
  ]
}
```

Search results are candidates, not saved books, so they carry a `search_url`
rather than a permanent slug. The book is created when a person follows that
link. If you build these links yourself on a server, append `&human=1`.

## Things that will trip you up

1. **Do not send `Referer: https://booklink.fyi`** (the bare origin, no path, no
   trailing slash). Every route, including the API, answers that with `403`.
   Links from your own site are unaffected; this only bites hand-rolled HTTP
   clients that set a Referer.
2. **Use an honest `User-Agent`, and keep the words `crawler`, `spider` and
   `scraper` out of it.** Requests that identify as a known search, AI or
   uptime-monitoring bot, or contain those words, can read existing books but
   never create new ones. An automated check of
   `/isbn/{isbn}` for a book we have not seen yet will therefore get a 404 that a
   real reader would not.
3. **Do not crawl or prefetch** `/search`, `/isbn/`, `/resolve`, `/go/` or `/api/`.
   They are disallowed in `robots.txt` because following them creates records
   and logs clicks. Book pages (`/book/…`, `/b/…`) are fine to fetch.
4. **Calling from a server?** Your whole backend is one IP sharing the 20/minute
   anonymous limit. Ask for a key, and cache: a book's `slug` and `booklink_url`
   do not change.
5. **Content-Security-Policy.** Plain links need nothing. If you call the API
   from the browser, add `https://booklink.fyi` to `connect-src`. Our cover
   images are served from several hosts, so `img-src https:` is the practical setting.

## Affiliate links and what is coming

Retailer links on BookLink.fyi pages carry BookLink's affiliate tags; that is
what pays for the service. Three things are planned but **not available yet**:

- registered partners using **their own affiliate tags** on the retailers where
  they have a program;
- a **JSON endpoint returning a book's retailer links**, so you can render the
  buttons on your own page in your own design;
- a **drop-in embed** (script tag or iframe) for sites without a developer.

If one of those would change what you build, tell us — it decides the order we
build them in: hello@booklink.fyi
