Books — entry 006 of 22
Crossref Metadata Search
Crossref's REST API is a keyless way to search and retrieve bibliographic metadata — titles, authors, funders, references, licensing — for the 160-million-plus scholarly works it has assigned DOIs to, spanning journal articles, books, chapters, and datasets. Anonymous requests land in a low-throughput default pool; adding a mailto contact parameter moves you into a faster, still-free "polite" pool, and a paid Metadata Plus subscription removes the concurrency cap for production integrations. It's run directly by the Crossref non-profit rather than a third party.
Crossref's REST API is a keyless way to search 160-million-plus scholarly works by bibliographic string and get back trimmed JSON metadata — title, DOI, type — via a select= parameter that shrinks the payload to only the fields asked for. A live GET this run against /works?query.bibliographic=atlas+of+api&rows=1&select=title,DOI,type returned a genuine 300 B single-result record; the byte-identical query with select= removed returned 1,915 B, so the trimming is real rather than cosmetic.
GreatAPIs Score
Auth quickstart
- No API key, signup, or credit card required for the base search — a live GET this run returned real results with zero credentials. Adding a
mailto=query parameter (any real contact address) moves the same request into Crossref's faster "polite pool": a live GET this run withmailto=test@example.comon the identical query returnedx-rate-limit-limit: 3/x-api-pool: polite-array, versusx-rate-limit-limit: 1/x-api-pool: public-arrayon the anonymous request moments before — both still fully free, no key ever issued.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
Search scholarly works by bibliographic string, trimmed to three fields
GEThttps://api.crossref.org/works?query.bibliographic=atlas+of+api&rows=1&select=title,DOI,type
{"status":"ok","message-type":"work-list","message-version":"1.0.0","message":{"facets":{},"total-results":177895,"items":[{"title":["atlas: Stanford 'ATLAS' Search Engine API"],"DOI":"10.32614\/cran.package.atlas","type":"dataset"}],"items-per-page":1,"query":{"start-index":0,"search-terms":null}}}select=title,DOI,type is what keeps this 300 B — dropping it from this exact query, and changing nothing else, returned 1,915 B on a live GET this run. Separately, and not a select= comparison since that route rejects the parameter outright (see the gotchas): the single-work route returns each record in full by default — abstract, references, funders, license terms — which is why a live GET this run against /works/10.1371/journal.pone.0000308 ran 11,960 B for that one work.
Try it
Developer reference
https://api.crossref.org1 request/second anonymously (`x-rate-limit-limit: 1`, confirmed live this run); adding a `mailto=` contact parameter to enter the free "polite pool" raises this to 3 requests/second (`x-rate-limit-limit: 3`), confirmed live the same run. A separate `/works/{doi}` single-work lookup draws from its own pool at 5 requests/second.
- GET/works
- GET/works/{doi}
Gotchas & limits
- Anonymous and polite-pool requests carry genuinely different rate limits in their own headers — confirmed live this run on the identical query: the anonymous call returned
x-rate-limit-limit: 1/x-rate-limit-interval: 1s/x-api-pool: public-array, while addingmailto=test@example.comreturnedx-rate-limit-limit: 3/x-api-pool: polite-array— three times the throughput for one added query parameter, no signup required. - A single-DOI lookup (
/works/{doi}) draws from a third, separate pool — a live GET this run against/works/10.1371/journal.pone.0000308returnedx-rate-limit-limit: 5/x-api-pool: public-single, a different limit and pool name than either search variant above. select=genuinely shrinks the payload, not just which keys are visible — confirmed live this run with a like-for-like pair on one identical query:/works?query.bibliographic=atlas+of+api&rows=1&select=title,DOI,typereturned 300 B, while the same request withselect=simply removed returned 1,915 B. About a 6x saving on a single-result query, and it compounds asrows=grows.select=is rejected outright on the single-work route — a live GET this run against/works/10.1371/journal.pone.0000308?select=title,DOI,typereturned a genuine HTTP 400 with a 164-byte{"status":"failed","message-type":"validation-failure","message":[{"type":"parameter-not-allowed","value":"select","message":"This route does not support select"}]}. That same record fetched the only way that route allows — noselect=— ran 11,960 B live this run, so a per-DOI lookup is both fat and untrimmable. To get one work trimmed, query it through the search route instead: a live GET this run against/works?filter=doi:10.1371/journal.pone.0000308&rows=1&select=title,DOI,typereturned the same work at 336 B.- A DOI's own slash (e.g.
10.1371/journal.pone.0000308) is passed as a literal, unencoded path segment after/works/— confirmed live this run — Crossref's own route parses everything after/works/as the DOI, so it doesn't need URL-encoding.
Changelog
- gained rate limits