Introduction
In February 2026, the v1.0 of the Distributed Text Services (DTS) specification was officially released — a standard API for accessing text collections.
This article documents the changes required to migrate the Kouigenji Monogatari Text Database DTS API from 1-alpha to 1.0.
https://github.com/distributed-text-services/specifications/releases/tag/v1.0
What is DTS?
DTS defines a standard API for accessing text collections such as TEI/XML. It consists of four endpoints:
| Endpoint | Purpose |
|---|---|
| Entry Point | Returns URLs for each API endpoint |
| Collection | Inter-text navigation (listing collections and resources) |
| Navigation | Intra-text navigation (exploring citation structures) |
| Document | Retrieving text content (full or partial TEI/XML) |
Target Project
A TypeScript/Express.js implementation of DTS for the Kouigenji Monogatari Text Database.
- Production: https://dts-typescript.vercel.app/api/v2/dts
- Source code: https://github.com/nakamura196/dts-typescript
Key Changes from 1-alpha to 1.0
1. JSON-LD Context URL Change
The most fundamental change is the JSON-LD context file URL.
- "@context": "https://distributed-text-services.github.io/specifications/context/1-alpha1.json"
+ "@context": "https://dtsapi.org/context/v1.0.json"
The domain changed from distributed-text-services.github.io to dtsapi.org, reflecting the assignment of a persistent URL with the official release.
2. dtsVersion Update
- "dtsVersion": "1-alpha"
+ "dtsVersion": "1.0"
The dtsVersion field in all endpoint responses must be updated.
3. Full Parameter Listing in URI Templates
In 1-alpha, only some parameters were listed, but 1.0 requires all accepted parameters in URI templates.
Entry Point response example:
{
- "collection": "/api/v2/dts/collection{?id}",
- "navigation": "/api/v2/dts/navigation{?resource,ref,down}",
- "document": "/api/v2/dts/document{?resource,ref}"
+ "collection": "/api/v2/dts/collection{?id,page,nav}",
+ "navigation": "/api/v2/dts/navigation{?resource,ref,start,end,down,tree,page}",
+ "document": "/api/v2/dts/document{?resource,ref,start,end,tree,mediaType}"
}
Added parameters:
| Parameter | Endpoint | Purpose |
|---|---|---|
page | Collection, Navigation | Pagination |
nav | Collection | children (default) or parents |
start / end | Navigation, Document | Range specification (mutually exclusive with ref) |
tree | Navigation, Document | Citation Tree selection |
mediaType | Document | Response media type specification |
4. Stricter Content-Type
JSON responses that used application/json in 1-alpha must now use application/ld+json in 1.0.
// JSON-LD responses (Entry Point, Collection, Navigation)
res.set("Content-Type", "application/ld+json");
// Document responses
res.set("Content-Type", "application/tei+xml");
| Endpoint | Old Content-Type | New Content-Type |
|---|---|---|
| Entry Point / Collection / Navigation | application/json | application/ld+json |
| Document | application/xml | application/tei+xml |
5. Link Header for Document Endpoint
Document endpoint responses now require a Link header pointing to the Collection endpoint.
res.set("Link", `</api/v2/dts/collection?id=${resource}>; rel="collection"`);
Example response headers:
Content-Type: application/tei+xml; charset=utf-8
Link: </api/v2/dts/collection?id=urn:kouigenjimonogatari.1>; rel="collection"
6. Changed Behavior of Navigation down Parameter
In 1-alpha, down had a default value, but in 1.0 its presence or absence significantly changes behavior.
down | ref | Behavior |
|---|---|---|
| absent | absent | 400 Bad Request |
| absent | present | Return ref info only (no member array) |
| 1+ | absent | Return member array from root to specified depth |
| 1+ | present | Return member array from ref to specified depth |
| -1 | either | Return all levels to deepest |
| 0 | present | Return siblings sharing same parent as ref |
// 1-alpha: default down=1
if (down === undefined) {
down = "1";
}
// 1.0: 400 if down, ref, and start/end are all absent
if (down === undefined && !ref && !start && !end) {
res.status(400).json({ error: "down, ref, or start/end is required" });
return;
}
7. CitableUnit identifier Field
Navigation response ref objects now use identifier instead of @id.
navigationData["ref"] = {
- "@id": refString,
+ "identifier": refString,
"@type": "CitableUnit",
"level": 1,
"parent": null,
"citeType": "page"
}
8. Parameter Validation
DTS 1.0 requires clear 400/404 responses for invalid parameter combinations.
// ref and start/end are mutually exclusive
if (ref && (start || end)) {
res.status(400).json({ error: "ref cannot be used with start/end" });
return;
}
// start and end must be used together
if ((start && !end) || (end && !start)) {
res.status(400).json({ error: "start and end must be used together" });
return;
}
Level 0 and Level 1
DTS 1.0 defines conformance levels:
- Level 0:
start/endparameter implementation not required (intended for static file implementations) - Level 1: Full parameter support
This implementation targets Level 0 conformance. All parameters are listed in URI templates, but start/end return validation errors when used. This is correct behavior per the specification.
A Level 0 DTS Server need not support the start and end parameters for the Navigation endpoint. It SHOULD raise an error if either of these parameters are used in a request.
Waka Navigation with Multiple Citation Trees
DTS 1.0 allows defining multiple Citation Trees per resource. The Kouigenji Monogatari TEI/XML contains waka (tanka poems) embedded as <lg type="waka"> elements.
<lg xml:id="waka-001" type="waka" rhyme="tanka">
<l n="1">かきりとて</l>
<l n="2">わかるゝ道の</l>
<l n="3">かなしきに</l>
<l n="4">いかまほしきは</l>
<l n="5">いのちなりけり</l>
</lg>
A dedicated waka Citation Tree was added alongside the default page/line navigation.
citationTrees Definition
{
"citationTrees": [
{
"@type": "CitationTree",
"citeStructure": [
{ "citeType": "page", "citeStructure": [{ "citeType": "line" }] }
]
},
{
"@type": "CitationTree",
"identifier": "waka",
"description": "Citation structure by waka (tanka) poems",
"citeStructure": [
{ "citeType": "waka", "citeStructure": [{ "citeType": "ku" }] }
]
}
]
}
Per DTS 1.0:
- The default Citation Tree (first) has no
identifier - Subsequent Citation Trees have an
identifier descriptionis optional for human-readable explanation
Using the tree Parameter
Clients switch between Citation Trees using the tree parameter.
# Default (page/line) navigation
/navigation?resource=urn:kouigenjimonogatari.1&down=1
# Waka tree listing
/navigation?resource=urn:kouigenjimonogatari.1&tree=waka&down=1
# Waka tree all levels (poems + verses)
/navigation?resource=urn:kouigenjimonogatari.1&tree=waka&down=-1
# Get a specific waka's XML
/document?resource=urn:kouigenjimonogatari.1&tree=waka&ref=waka-001
# Get only the 3rd verse
/document?resource=urn:kouigenjimonogatari.1&tree=waka&ref=waka-001.3
Implementation Notes
Citation Trees are defined in src/utils/citationTrees.ts and shared across Collection, Navigation, and Document endpoints.
The Navigation endpoint dispatches to different member map building functions based on the tree parameter:
if (treeString === "waka") {
buildWakaMembersMap(xmlDoc, membersMap); // Traverse <lg type="waka">
} else {
buildDefaultMembersMap(xmlDoc, membersMap); // Traverse <seg corresp="...">
}
The Document endpoint extracts <lg xml:id="waka-001"> when tree=waka and ref=waka-001 are specified. For verse-level references (ref=waka-001.3), only the matching <l n="3"> is returned.
Test Suite
Tests were added using vitest with 29 test cases verifying DTS 1.0 compliance.
npm test
Tests cover:
- Response format for each endpoint (Context URL, dtsVersion, @type)
- Content-Type headers (
application/ld+json,application/tei+xml) - Full parameter listing in URI templates
- Document Link header
- Validation (400/404 errors)
- Navigation
downparameter behavior - Waka navigation (
tree=waka) poem and verse retrieval - Waka document retrieval (full poem, single verse)
Changed Files
| File | Changes |
|---|---|
src/api/v2/dts.ts | Context URL, dtsVersion, URI templates, Content-Type |
src/api/v2/collection.ts | Same + page/nav params, shared citationTrees |
src/api/v2/navigation.ts | Same + down behavior, validation, identifier, tree=waka |
src/api/v2/document.ts | Content-Type application/tei+xml, Link header, validation, tree=waka |
src/utils/citationTrees.ts | Shared Citation Trees module (new) |
src/__tests__/dts-v2.test.ts | 29 vitest test cases |
Conclusion
DTS 1.0 is a specification refined through years of development and interoperability testing. While changes from 1-alpha are relatively small, they include production-oriented improvements such as stricter Content-Type handling and parameter validation.
By implementing a DTS-compliant API when publishing TEI/XML texts in Digital Humanities, interoperability with existing DTS clients is achieved.