This HTTP Key => Value API was set up to provide a sane way to access (meta) data of books in print in the Netherlands in a simple machine programmable way.
It was created to address our own frustrations, but is provided as a free service for anybody to use. The usage will always be free, but we can not guarantee that this service will be around forever. If at any time in the future CB / TitelBank provides a service that adresses the fundamental needs that any online bookshop runs into, this service will be fased out.
The 3 problems adressed are:
NB: a valid contact email-address has to be provided in every API call if you use it more then incidentally. This provides us a way of contacting you in case of any detected problems.
Failure to provide a valid contact address in the header will lead to blocking of your IP/CIDR in case of incorrect or unreasonable usage
It’s quite simple to use. Simply HTTP GET:
https://easycbapi.nl/isbn/the-isbn-nummer
And it will output any information it has about this ISBN in a simple key:value format
Example: https://easycbapi.nl/isbn/9789083316642
Example using curl:
shell> curl -s -H "contact: developer_to_contact@example.org" https://easycbapi.nl/isbn/9789002219788
isbn:9789002219788
title:Het generatiepact
author:B. Huygebaert
mutationlog:
ProductSupply.SupplyDetail.Price.CurrencyCode:EUR
ProductSupply.SupplyDetail.Price.PriceAmount:9.95
ProductSupply.SupplyDetail.Price.PriceType:02
ProductSupply.SupplyDetail.ProductAvailability:99
CollateralDetail.TextContent.TextType:05
DescriptiveDetail.Contributor.ContributorRole:A01
DescriptiveDetail.Contributor.KeyNames:Huygebaert
DescriptiveDetail.Contributor.NamesBeforeKey:B.
DescriptiveDetail.Contributor.PersonName:B. Huygebaert
DescriptiveDetail.Contributor.SequenceNumber:1
DescriptiveDetail.EditionNumber:1
DescriptiveDetail.Extent.ExtentType:00
DescriptiveDetail.Extent.ExtentUnit:03
DescriptiveDetail.Extent.ExtentValue:168
DescriptiveDetail.Illustrated:01
DescriptiveDetail.Language.LanguageCode:dut
DescriptiveDetail.Language.LanguageRole:01
DescriptiveDetail.NoCollection:
DescriptiveDetail.ProductComposition:00
DescriptiveDetail.ProductForm:BC
etc.
To receive a list of all ISBN’s that have been changed since date X, use :
https://easycbapi.nl/isbn-since/20241201
The date has to be provided in the UNIX POSIX format ‘%Y%m%d’, meaning: full-year, the number of the month and the number of the day.
Example of a valid date: 20241130
It can be generated with the Unix command:
shell> date '+%Y%m%d'
20241130
Or more likely with a strftime function or its derivatives:
strftime("%Y%m%d", timestamp )
So a call to the /isbn-since/ API in curl can be :
shell> curl -s -H "contact: developer_to_contact@example.org" https://easycbapi.nl/isbn-since/20241030 | head
9789000035588
9789000035960
9789000301096
9789000301355
9789000305155
9789000309757
9789000314720
9789000321834
9789000330409
9789000330416
A note of warning: If for whatever reason we are out of sync with Centraal Boekhuis, and forced to do a completely new import, it will list ALL ISBN’s as modified!
To get a list of all ISBN’s published use:
shell> curl -s -H "contact: developer_to_contact@example.org" https://easycbapi.nl/isbn-since/all | wc -l
1950906
A simple, crude and inefficient way to use the API call’s combined would be :
#!/bin/sh
# What date was the update last run?
DATE = `cat last_run_date.state`
# fetch updated ISBN's since this date, and runs update_isbn with each changed ISBN
curl -s -H "contact: developer_to_contact@example.org" https://easycbapi.nl/isbn-since/$DATE | xargs -r -i sh -c 'curl -s -H "contact: developer_to_contact@example.org" https://easycbapi.nl/isbn/{} | ./update_isbn {} '
# ./update_isbn takes the first command-line arg as the name of the ISBN, and reads key:values from its STDIN.
# how it updates the data in a database is implementation dependent and beyond this example
# update the last_run_date.state state file
date '+%Y%m%d' > last_run_date.state
This of course has no error checking, and is very inefficient, since it spawns a new process for every update. It also does not first filter the ISBN to check, but it shows how one could use the combined API’s, and is simple to read and understand.
Another example in which you update all of your book information:
#!/bin/sh
#
# in this case you have a CSV file that lists all ISBN's your shop caries in the first field, and dump them to STDOUT with the cat books.csv |awk -F, '{print $1}'
# the sed -e 's/"//' is there to strip away "" from "9789083117614" which some CSV exports put around any value.
cat books.csv |awk -F, '{print $1}' | sed -e 's/"//' | xargs -r -i sh -c 'curl -s -H "contact: developer_to_contact@example.org" https://easycbapi.nl/isbn/{} | ./update_isbn {}'
Resources of a ISBN such as book covers can also be fetched.
You can retrieve any cover / with the URL:
https://easycbapi.nl/resources/jpg/(resource)
For example the resource links from ISBN 9789046828540 are:
shell> curl -s https://easycbapi.nl/isbn/9789046828540| grep 'ResourceLink'
CollateralDetail.SupportingResource.1.ResourceVersion.ResourceLink:9789046828540_VRK.jpg
CollateralDetail.SupportingResource.2.ResourceVersion.ResourceLink:9789046828540_DVB.pdf
CollateralDetail.SupportingResource.0.ResourceVersion.ResourceLink:9789046828540_ATK.jpg
And they can be fetched from :
https://easycbapi.nl/resources/jpg/9789046828540_VRK.jpg
https://easycbapi.nl/resources/jpg/9789046828540_ATK.jpg
https://easycbapi.nl/resources/pdf/9789046828540_DVB.pdf
To prevent hot-linking the referrer must either be empty, or the site itself.
In other words: if you simply fetch the resource everything should be ok, but hot-linking won’t work.
To see all the ONX historical info for a ISBN, simply append the isbn URL with .log to /isbnlog/ This will show when any ISBN was updated, and with what info.
For example:
shell> curl -s https://easycbapi.nl/isbnlog/9789046828540.log
20230809 CollateralDetail.SupportingResource.ContentAudience:03
20230809 CollateralDetail.SupportingResource.ResourceContentType:15
20230809 CollateralDetail.SupportingResource.ResourceMode:03
20230809 CollateralDetail.SupportingResource.ResourceVersion.ResourceForm:01
20230809 CollateralDetail.SupportingResource.ResourceVersion.ResourceLink:9789046828540_DVB.pdf
20230809 CollateralDetail.TextContent.ContentAudience:03
20230809 CollateralDetail.TextContent.Text:Actiegerichte Amerikaanse doorlezer.
20230809 CollateralDetail.TextContent.TextSourceCorporate:volkskrant
20230809 CollateralDetail.TextContent.TextType:06
20230809 DescriptiveDetail.Contributor.ContributorRole:B06
20230809 DescriptiveDetail.Contributor.KeyNames:Noë
20230809 DescriptiveDetail.Contributor.NamesBeforeKey:Waldemar
20230809 DescriptiveDetail.Contributor.PersonName:Waldemar Noë
20230809 DescriptiveDetail.Contributor.SequenceNumber:4
The format is:
date tab key:value
A thing to note is that this service depends on the completeness and correctness of the Titelbank ONIX info. Unfortunately the Titelbank ONIX dumps are incomplete, missing updates and in general not in the best state.
A big part of the problem is that ONIX files don’t provide the correct data, but provides updates, on top of older data, encoded in XML. It’s like ONIX (AAP, EDItEUR, et al. ) took a old EDI standard and encoded it in XML.
If you’re going to have to deal with the ONIX standard, you will need to read these links
Contact questions@easycbapi.nl if you have questions, experience problems, have remarks or because you feel like it.
Caveat: If you don’t understand the listed examples, this API is probably not for you.