Documentation
Resolver & Enterprise API
isbn.link implements the GS1 Digital Link URI Syntax and GS1-Conformant Resolver standards.
URI syntax
ISBN-13 is treated as GTIN. Values are normalized to 14 digits with a leading zero. Canonical form uses numeric Application Identifiers:
https://isbn.link/01/{GTIN-14}
https://isbn.link/01/{GTIN}/10/{lot}
https://isbn.link/01/{GTIN}/10/{lot}/21/{serial}
https://isbn.link/01/{GTIN}/22/{cpv}/10/{lot}/21/{serial}
# Qualifier order (required): CPV (22) → lot (10) → serial (21)
# Legacy alpha /gtin/... is accepted and mapped to AI 01Why are my 13-digit ISBNs represented as 14 digits?
(or, what's with the leading 0?)
Your ISBN-13, for example 9781961451216, is a 13-digit GTIN. In a GS1 Digital Link, the GTIN (Application Identifier 01) is always written with 14 digits, so 13-digit GTINs get a leading 0:
ISBN-13: 978-1-961451-21-6 GTIN in the link: 09781961451216 Digital Link (QR): https://isbn.link/01/09781961451216
This is required by the GS1 Digital Link Standard: URI Syntax (release 1.7.0, 6 August 2026; PDF):
- §4.1, Removal of convenience alphas and GTIN values expressed using fewer than 14 digits: GTIN-8, GTIN-12, and GTIN-13 values are expressed as 14 digits, padded with leading zeros. Shorter forms are legacy, still accepted by existing systems for compatibility.
- §4.5, Primary identification key formats: the URI grammar defines the GTIN value as exactly 14 digits.
- §4.12, Canonical form: GTINs stay padded to 14 digits.
What this means for you
- Your ISBN doesn't change. The leading 0 is only filler: it's the same book, and the check digit is unaffected. The ISBN printed on the book and its EAN-13 barcode stay 13 digits.
- QR codes always use 14 digits. That keeps them valid GS1 Digital Links that retail point-of-sale scanners and GS1 apps accept. GS1's reference barcode engine rejects a 13-digit GTIN here as “too short”.
- Both forms resolve. As §4.1 asks of existing systems, isbn.link also accepts the 13-digit form, so
https://isbn.link/01/9781961451216works in links you type or share. Use the 14-digit form for anything printed.
Resolution behaviour
New to link types? Start with the guide How link types work, which walks through setups with examples.
- Default: HTTP 307 to the link typed
gs1:defaultLink. - linkType:
?linkType=gs1:pipredirects to that type; missing type returns404. - Invalid URI:
400 Bad Requestwith structured error body. - Unknown GTIN:
404 Not Found(never200on error). - CORS: enabled for GET, HEAD, OPTIONS as required by the resolver standard.
- Link headers: available resources exposed via HTTP
Link.
Linksets
Request the full set of links without redirecting:
GET /01/{GTIN}?linkType=linkset
GET /01/{GTIN}?linkType=all
Accept: application/linkset+json
# Response: application/linkset+json (RFC 9264 profile)Hosted pages
A title can have several pages hosted on isbn.link, each for one purpose: where to buy, reviews, a book-club guide, accessible formats, and so on. Create them in the portal under Hosted pages; each starts from a template for its link type and is built from sections you can add, remove, and reorder:
- Book info: the full product details, or a compact header with cover, title, author, and price.
- Text: a heading and paragraphs.
- Buttons: store presets and custom links;
{isbn13}fills in the scanned edition's ISBN. - Video: YouTube, Vimeo, Instagram, or a video file.
- Quotes: review quotes or praise with their source.
- Formats: links to every edition of the book.
In Link Type Mapping, each mapping's target is either a hosted page or a custom URL. Choosing New … page (default) creates the page from its link type's template when you save. Empty sections are hidden, and a page can't be deleted while a mapping points at it.
GET /p/{titleId}/{pageId}?gtin={GTIN} → a hosted page (mappings add ?gtin=)
GET /p/{titleId} → the title's Product page
(standard layout until you customize it)Reader journeys
A title can send scans through a sequence of screens instead of a single page: a trailer, the hosted book page with store buttons, then more links (Pro). The journey becomes the title's default link, so it answers plain scans while other link types keep working. See the guide Reader journeys.
GET /01/{GTIN} → 307 to /f/{titleId}?gtin={GTIN}
GET /f/{titleId} → first visible step (?step= selects one)
GET /f/{titleId}/go → counts a button tap, 302 to its saved URL
# Journey off or no visible steps: /f/{titleId} → 307 to /p/{titleId}Enterprise API
Authenticate with Authorization: Bearer il_… keys from the portal (Pro+).
/api/v1/itemsList/search catalog formats. Query: q, isbn, gtin, titleId, limit (1–500), offset. Returns work_name when linked to a title.
/api/v1/itemsCreate item. Body: { "isbn": "978…", "title": "…", "defaultLink": { "href": "…" } }
/api/v1/links?gtin=List links for a GTIN.
/api/v1/linksRegister link. Body: { "isbn", "linkType", "href", "isDefault?", "qualifiers?" }. Advanced: qualifiers limits the link to scans with a GS1 key qualifier, e.g. { "10": "RUN3" } (AI 22, 10, 21, or 235; one alone or 22 with 10; short names lot, ser, cpv, tpx are accepted).
/api/v1/barcodesGenerate barcode. Body: { "isbn", "symbology": "qrcode|datamatrix|ean13|composite", "format": "svg|png", "baseUrl"?, "includeSrp"?, "srp": "$19.99"?, "layout"?, "scale"?, "overlay": "none|scan-me|learn-more|interactive|more-info|custom"?, "overlayText"?, "overlayArrowStyle": "arc|brush|chevron|curve-down"?, "overlayTextStyle": "script|bold|sans|serif"?, "overlayArrowColor"?, "overlayTextColor"?, "overlayArrowWeight"?, "overlayPhoneIcon"?, "overlayPhoneIconScale"?, "overlayLayout"?, "attributes"? }. Advanced: attributes adds GS1 data-attribute AIs to the Digital Link query string, e.g. { "11": "240301" } for a production date (AIs 11, 15, 17, 3103; dates YYMMDD; set prices with srp). Callouts sit in a band above the symbols (never cover QR/UPC). PNG matches SVG (sharp). Responses include X-Digital-Link-URI headers.
Barcodes
2D symbols encode the full Digital Link URI (scan → resolve). 1D EAN-13 encodes the GTIN for POS. Optional SRP expands the linear symbol with a Bookland EAN-5 price add-on ($19.99 → 51999) and encodes amount payable with ISO currency on the Digital Link (AI 3912, e.g. ?3912=8401999). Contrast analysis flags low-contrast and risky red/brown foregrounds per GS1 print guidance.
Optional consumer overlays bake a callout (e.g. “Scan me!”, “Interactive!”) with a curved arrow and optional phone glyph into SVG/PNG. Graphics live in a band above the barcode only; they never cover QR or UPC modules. PNG is a sharp raster of the same SVG as the studio preview. Options: overlay, overlayText, overlayArrowStyle (arc|brush|chevron|curve-down), overlayTextStyle (script|bold|sans|serif), overlayArrowColor / overlayTextColor, overlayArrowWeight, overlayPhoneIcon + overlayPhoneIconScale (0.25–1 of QR height), and overlayLayout (normalized drag handles for text + arrow tip).
InDesign plugin
Cover designers can search the publisher catalog and place dual-mark (QR + EAN), QR, EAN-13, or Data Matrix symbols from inside Adobe InDesign without leaving the layout. The panel calls the Enterprise API with a Pro+ API key; barcodes are generated on the server so quiet zones and Digital Link URIs match the portal Barcode Studio.
- Source:
indesign-plugin/(UXP panel, InDesign 2024+) - Install: sideload with Adobe UXP Developer Tools; Marketplace packaging is planned later
- Auth: portal Settings → API key → paste into plugin Settings
- Guide:
docs/indesign-plugin.md
Affinity script
Affinity by Canva does not yet offer a dockable third-party panel SDK comparable to Adobe UXP. isbn.link ships a Scripts panel tool that uses the same Enterprise catalog and barcode APIs as the InDesign plugin. Host place APIs are confirmed via a Phase 0 SPIKE on real Affinity builds.
- Source:
affinity-plugin/(single-file JS for Window → Scripts) - Auth: same Pro+
il_…API keys - Guide:
docs/affinity-plugin.md
Resolver description
Machine-readable capability document required by the Conformant Resolver standard:
/.well-known/gs1resolverTry it
Demo titles are seeded for local exploration. After adding your own ISBNs in the portal:
curl -i https://isbn.link/01/09780201616224 curl -H 'Accept: application/linkset+json' \ https://isbn.link/01/09780201616224