Adjuncts
Any asset in the platform can have a list of linked files, which can be externally hosted or hosted by the platform. For an image asset, a linked file might be OCR text derived from the image, or web annotations transcribing the image, or a spectral analysis, or in fact any kind of data you need to attach to the asset. For AV assets, an adjunct might be a WebVTT captions file.
Adjuncts are linked in the API from the asset to a Hydra collection:
{ "@context": "https://dlcs.github.io/vocab/context/future.json", "@id": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2", "@type": "vocab:Image",
"adjuncts": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts"
}This is a Hydra collection of files associated with the asset, and stored and served by the platform. A GET on that URI might return:
{ "@context": "https://dlcs.github.io/vocab/context/future.json", "@id": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts", "@type": "Collection", "totalItems": 2, "member": [ { "@id": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/b2921371x_0001.xml", "@type": "Dataset", "publicId": "https://dlcs.example/adjuncts/2/5/b2921371x_0001.jp2/b2921371x_0001.xml", "label": { "en": [ "METS-ALTO text for b2921371x_0001.jp2" ] }, "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "language": [ "en" ], "origin": "https://s3-eu-west-1.amazonaws.com/example-bucket/digitised/b2921371x/v1/data/objects/alto/b2921371x_0001.xml", "roles": [], "size": 240563, "iiifLink": "seeAlso", "motivation": null, "provides": null, "ingesting": false, "error": null, "created": "2025-09-22T16:45:29+00:00", "finished": "2025-09-22T16:45:32+00:00", "content": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/b2921371x_0001.xml/content" }, { "@id": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/b2921371x_0001.anno.json", "@type": "AnnotationPage", "publicId": "https://dlcs.example/adjuncts/2/5/b2921371x_0001.jp2/b2921371x_0001.anno.json", "label": { "en": [ "IIIF Annotations for b2921371x_0001.jp2" ] }, "mediaType": "application/json", "language": [ "en" ], "roles": [], "creator": "pipeline:annotationsFromOCR/v0.9.1", "source": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/b2921371x_0001.xml", "size": 390553, "iiifLink": "annotations", "motivation": null, "provides": null, "ingesting": false, "error": null, "created": "2025-09-22T16:49:29+00:00", "finished": "2025-09-22T16:49:32+00:00", "content": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/b2921371x_0001.anno.json/content" } ]}There is no vocab:Adjunct type because an adjunct can be any kind of resource. Here the first adjunct has @type Dataset (from Dublin Core via IIIF) and the second is AnnotationPage. It is recommended to use types defined by IIIF, so that when your adjuncts are encountered in a IIIF Manifest the type property is from a known vocabulary. This isn’t mandatory, they can be anything.
In the above example, the first adjunct is a METS-ALTO file and was supplied via an origin in the same way that assets are supplied: the platform fetched it from the origin, using the same customer origin strategies if necessary. The second example does not have an origin but does have a creator with the value "pipeline:annotationsFromOCR". This second adjunct was made by the platform itself from the first adjunct (specified by the source field), using the pipeline specified by the creator field.
Creating and registering Adjuncts
Section titled “Creating and registering Adjuncts”An adjunct can either be external (hosted somewhere else), or hosted by the platform. If external, the platform has nothing to do with serving the adjunct and merely records the link between the asset and the external resource. This is still useful because that link can be expressed in generated IIIF. At registration time, you specify the externalId property, which will remain the public URL of the adjunct.
If it is to be hosted by the platform, you specify an origin when creating the adjunct, in the same way origin works for assets.
In both cases the publicId of the adjunct shows where end-users will load the adjunct from (and where IIIF resources should link to), but for adjuncts registered from an origin, the publicId will be a platform-managed URL.
Adjuncts can be created by a POST to the asset’s adjuncts property URL, or a PUT directly to the API @id under that URL.
Creating an adjunct that links to an external URL
Section titled “Creating an adjunct that links to an external URL”POST https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts{ "id": "mets-external", "externalId": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "size": 36032, "iiifLink": "seeAlso", "language": [ "en" ]}or by PUT (id is optional but if present, must match the PUT URL):
PUT https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-external{ "externalId": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "size": 36032, "iiifLink": "seeAlso", "language": [ "en" ]}In both these cases the request will return HTTP 201 Created, and the created adjunct is available immediately and looks like this:
GET https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-externalreturns:
{ "@id": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-external", "publicId": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "size": 36032, "iiifLink": "seeAlso", "motivation": null, "provides": null, "ingesting": false, "error": null, "created": "2025-09-22T16:49:29+00:00", "finished": "2025-09-22T16:49:29+00:00", "language": [ "en" ], "roles": []}While roles can be specified when creating an adjunct via externalId, and will be stored on the adjunct, the platform will ignore them when serving the adjunct as it has no means of enforcing them.
Creating an adjunct from an origin
Section titled “Creating an adjunct from an origin”In this case the content of the adjunct will be fetched from the origin and thereafter served by the platform on a managed URL. Note that we do not need to supply a size (if we do it will be ignored) as the platform will measure and store the actual size (in bytes).
POST https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts{ "id": "mets-from-origin.xml", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "iiifLink": "seeAlso", "language": [ "en" ]}or by PUT (id is optional but if present, must match the PUT URL):
PUT https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-from-origin.xml{ "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "iiifLink": "seeAlso", "language": [ "en" ]}In both these cases the request will return HTTP 201 Created immediately (the adjunct information is available immediately), but the ingesting property will be true and will continue to have that status until the adjunct content has been fetched from the origin and stored, at which point the ingesting property will be false. The created adjunct would look like this:
GET https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-from-origin.xmlreturns:
{ "@id": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-from-origin.xml", "@type": "Dataset", "publicId": "https://dlcs.example/adjuncts/5/2/b2921371x_0001.jp2/mets-from-origin.xml", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "size": 36032, "iiifLink": "seeAlso", "motivation": null, "provides": null, "ingesting": false, "error": null, "created": "2025-09-22T16:49:29+00:00", "finished": "2025-09-22T16:49:34+00:00", "language": [ "en" ], "roles": [], "content": "https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts/mets-from-origin.xml/content"}The content property is only for adjuncts hosted by the platform and will give the same binary response as the publicId. The difference is that the publicId is subject to any authorization flow implied by the adjunct’s roles, whereas the content URL is on the platform API and requires your API credentials rather than any external access control mechanism.
Registering multiple adjuncts
Section titled “Registering multiple adjuncts”An asset can have any number of adjuncts. They can be created/registered in separate HTTP operations as above, or in bulk by a POST to the asset’s adjunct endpoint. This POST to the asset’s adjuncts collection can take a single adjunct, an array of adjuncts, or a Hydra Collection with an array of adjuncts as member.
POST https://api.dlcs.example/customers/2/spaces/5/images/b2921371x_0001.jp2/adjuncts[ { "id": "mets-from-origin", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "iiifLink": "seeAlso" }, { "id": "annotations-from-origin", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.line.json", "@type": "AnnotationPage", "mediaType": "application/json", "label": { "en": [ "Line-level annotations" ] }, "iiifLink": "annotations" }]If an adjunct needs to be access-controlled, it specifies roles in the same way assets do, and the platform will emit IIIF Auth services when referencing the adjunct in a manifest.
Adjunct fields
Section titled “Adjunct fields”The API URL of the JSON resource. This is always of the form <asset-@id>/adjuncts/<adjunct-id>. It is not usually supplied by the API caller on a PUT or a POST. If it is supplied it must not conflict with any of the other fields that contribute to the URI.
The model id of the adjunct. Required on a POST when creating an adjunct, to provide a “filename” or last path element for the adjunct. The platform will not mint a value if one is not supplied (unlike assets). On a POST, it must not conflict with any of the asset’s other adjuncts. Optional on a PUT; if present, it must match the last element in the PUT URL path.
The id property, whether supplied explicitly in a POST or as the last path element in a PUT, appears in the public URL of the asset as served by the platform (see publicId).
For most platform types this is inferred from where the resource lives (what collection it’s in) but for adjuncts it must be specified. It has the same meaning as in the IIIF Presentation Specification (see type) and should use type values defined by that specification, like Dataset, Text or AnnotationPage. It will appear in any generated IIIF.
mediaType
Section titled “mediaType”This is the same as asset.mediaType — the internet content type (or MIME type) of the resource, the value that the platform will provide in the Content-Type header when it serves the adjunct’s binary content. If you are supplying the adjunct yourself, for the platform to store and serve, you must supply a mediaType. If you are asking the platform to create the adjunct, by specifying a creator that matches one of the platform’s known pipelines, you should not supply mediaType because the platform will set this itself.
Whenever the adjunct appears in a Manifest served by the platform, the value of this field is used as the format property.
profile
Section titled “profile”This is the same as the IIIF Presentation API profile property: ”… profile can further clarify the type and/or format of an external resource or service”. In the earlier example, the METS-ALTO file has:
{ "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd"}profile is informing a client that this XML resource is specifically a v3 ALTO file.
If you are supplying the adjunct yourself, for the platform to store and serve, you should supply a profile, but it is not mandatory and sometimes not relevant or possible. If you are asking the platform to create the adjunct, by specifying a creator that matches one of the platform’s known pipelines, you should not supply profile because the platform will set this itself.
This is the same as the IIIF Presentation API label property, and is a JSON LD Language Map (see the IIIF Presentation API). It is recommended to always supply this, and is required when supplying the adjunct yourself. For platform-generated adjuncts, a default label will be assigned if nothing is supplied.
language
Section titled “language”The language of an adjunct’s content, if applicable. The value is a JSON array of ISO language codes (sub-codes are allowed). See iiifLink for an example of how this property is used and how it appears in generated IIIF.
origin
Section titled “origin”Works in the same way as asset.origin and uses the same origin strategies where applicable. An origin is not allowed when asking the platform to create the adjunct via a pipeline, but is required when you are supplying an adjunct for the platform to host: the platform will fetch the content from the origin and serve it from a managed URL.
A string message from any error(s) encountered the last time this adjunct was processed. If re-processed the value will be cleared.
externalId
Section titled “externalId”Only valid when creating an adjunct. externalId is a fully-qualified URL external to the platform. The platform will not fetch or interrogate the URL in any way — unlike origin. The value of externalId will be expressed in IIIF as the id of the adjunct.
Works in the same way as asset.roles and accepts the same values. If specified, it will result in the platform enforcing access control. IIIF Authorisation Flow 2.0 services will be emitted on the adjunct in any generated manifests.
Unless you explicitly provide roles as an empty array, adjuncts will be assigned the roles of their parent asset.
creator
Section titled “creator”This is used to identify the process that created the adjunct — or if it has not been created yet, the process you want to invoke to create it. If you are supplying the adjunct yourself, for the platform to store and serve, you may supply a creator field which should be a fully qualified URI. The platform doesn’t make use of this information, it just stores it with the adjunct for your reference. The URI is an identifier for your external pipelines and processes.
If you are asking the platform to create the adjunct, you specify a value that matches one of the platform’s known pipelines. On initial PUT or POST the platform enqueues the adjunct to be processed by that pipeline.
See pipelines for more detail. You can ignore this property if supplying the content of adjuncts yourself.
source
Section titled “source”Only valid when you are asking the platform to create the adjunct via a pipeline — and even then, only when you need to specify one of the other adjuncts. In most cases the platform can work out what source you mean. For many pipelines, the source is the asset itself (e.g., OCR) and for others there may only be one other adjunct that could be a suitable source (as in the annotationsFromOCR example above).
If you are supplying the adjunct yourself, for the platform to store and serve, you may supply a source that makes sense to you, if some external process has been involved. If the platform is creating the adjunct it will always set the source field to either the asset @id or one of the other adjunct @id values, and return the value on subsequent GETs. Whenever the platform serves an adjunct, and there is a source, it will always appear as a full URL.
publicId
Section titled “publicId”The URL from which the adjunct’s binary content is served. This is a read-only property and will be ignored if supplied on a POST or PUT. This will appear as the adjunct’s IIIF id in any platform-generated IIIF manifest. If the adjunct was created from an origin, publicId will be of the form <base-url>/adjuncts/<customer>/<space>/<asset-id>/<adjunct-id>, e.g., https://dlcs.example/adjuncts/5/2/b2921371x_0001.jp2/mets-from-origin.xml, and access will be subject to any roles the adjunct has. If the adjunct was created or updated with externalId, the publicId is that value.
The size in bytes of the adjunct. This will be 0 if no content has been supplied yet, and it will be -1 if the origin has not been fetched or the asset has yet to be processed. For adjuncts created with externalId you can supply this yourself. For adjuncts served by the platform, it will be populated with the actual value whether you supply a value or not. For external adjuncts it is still optional; if absent, it will be omitted from the IIIF representation. As IIIF it appears as the fileSize property, introduced in IIIF Presentation 4.0.
iiifLink
Section titled “iiifLink”This property is required. Valid values are seeAlso, rendering, annotations and inlineAnnotation. When generating IIIF the platform will list an asset’s adjuncts under the equivalent IIIF properties of a Canvas, or as an inline annotation (see example below).
For example, an asset with four adjuncts created like this:
POST https://api.dlcs.example/customers/2/spaces/5/images/b29820947_0014.jp2/adjuncts[ { "id": "mets-from-origin.xml", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.xml", "@type": "Dataset", "mediaType": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "iiifLink": "seeAlso", "language": [ "en-GB", "cy" ] }, { "id": "annotations-from-origin.json", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.line.json", "@type": "AnnotationPage", "label": { "en": [ "Line-level annotations" ] }, "iiifLink": "annotations", "language": [ "en", "cy" ] }, { "id": "rendering-from-origin.jpg", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.jpg", "@type": "Image", "mediaType": "image/jpeg", "label": { "en": [ "A JPEG of the asset" ] }, "iiifLink": "rendering" }, { "id": "text-from-origin.txt", "origin": "https://dlcsstage-public-test-objects.s3.eu-west-1.amazonaws.com/images-with-text/b29820947_0014.jp2.txt", "@type": "Text", "mediaType": "text/plain", "label": { "en": [ "Plain text of this page" ] }, "language": [ "en", "cy" ], "iiifLink": "inlineAnnotation", "motivation": "supplementing", "provides": "transcript" }]… will produce an IIIF Canvas in a named query or single-asset manifest with three properties:
{ // many fields of Canvas omitted for brevity "id": "https://dlcs.example/iiif-img/2/5/b29820947_0014.jp2/canvas/c/1", "type": "Canvas", "seeAlso": [ { "id": "https://dlcs.example/adjuncts/2/5/b29820947_0014.jp2/mets-from-origin.xml", "type": "Dataset", "format": "text/xml", "profile": "http://www.loc.gov/standards/alto/v3/alto.xsd", "label": { "en": [ "METS-ALTO XML" ] }, "language": [ "en-GB", "cy" ], "fileSize": 36032 // computed } ], "annotations": [ { // iiifLink is "annotations", direct link to adjunct "id": "https://dlcs.example/adjuncts/2/5/b29820947_0014.jp2/annotations-from-origin.json", "type": "AnnotationPage", "label": { "en": [ "Line-level annotations" ] }, "language": [ "en", "cy" ], "fileSize": 12363 }, { // iiifLink is "inlineAnnotation" "id": "https://dlcs.example/adjunct-annotations/2/5/b29820947_0014.jp2", "type": "AnnotationPage", "label": { "en": [ "Inline annotations" ] }, "items": [ { "id": "https://dlcs.example/adjunct-annotations/2/5/b29820947_0014.jp2/text-from-origin.txt", "type": "Annotation", "motivation": [ "supplementing" ], "provides": [ "transcript" ], "body": [ { // adjunct is expressed as body of annotation "id": "https://dlcs.example/adjuncts/2/5/b29820947_0014.jp2/text-from-origin.txt", "type": "Text", "format": "text/plain", "label": { "en": [ "Plain text of this page" ] }, "language": [ "en", "cy" ], "fileSize": 9854 // computed } ], "target": [ "https://dlcs.example/iiif-img/2/5/b29820947_0014.jp2/canvas/c/1" ] } // If more than one adjunct with iiifLink: inlineAnnotations, they are added to this // single managed Annotation Page. ] } ], "rendering": [ { "id": "https://dlcs.example/adjuncts/2/5/b29820947_0014.jp2/rendering-from-origin.jpg", "type": "Image", "format": "image/jpeg", "label": { "en": [ "A JPEG of the asset" ] }, "fileSize": 909166 } ]}The property inlineAnnotation is not a valid IIIF property, but instead tells the platform to express the adjunct as an inline annotation on a “synthetic” annotation page, under the IIIF property annotations. This means adjuncts can appear directly linked from the annotations property, where the adjunct is itself an Annotation Page, or indirectly linked, where the adjunct is the body of an Annotation in an intermediate Annotation Page managed by the platform for this adjunct. The above example shows both of these.
motivation
Section titled “motivation”Only used when iiifLink is "inlineAnnotation". It appears as the motivation property of the annotation, as in the example above.
The value of motivation can be a single string or a comma-separated list of strings. The value will always appear in the resulting IIIF as an array of motivation values, whether there is one or more than one. The values should be taken from the W3C Web Annotation specification, or from the additional IIIF motivations provided by the Presentation API (e.g., “supplementing”).
provides
Section titled “provides”Only used when iiifLink is "inlineAnnotation". It appears as the provides property of the annotation, as in the example above.
The value of provides can be a single string or a comma-separated list of strings. The value will always appear in the resulting IIIF as an array of provides values, whether there is one or more than one. The values should be taken from the list defined in the IIIF Presentation specification (e.g., “audioDescription” or “subtitles”).
Adjunct creation field usage
Section titled “Adjunct creation field usage”See pipelines for further clarification of how these fields are used when invoking a platform pipeline.
The following table assumes that you are responsible for the binary content of the adjunct.
| Field | POST external | PUT external | POST from origin | PUT from origin | appears in IIIF |
|---|---|---|---|---|---|
@id | optional* | optional* | not allowed | optional* | no |
id | required | optional* | not allowed | optional* | as last path element if not external |
@type | required | required | required | required | yes, as type |
mediaType | recommended | recommended | recommended | recommended | yes, as format |
profile | optional | optional | optional | optional | yes, as profile |
label | required | required | required | required | yes |
language | optional | optional | optional | optional | yes |
origin | not allowed | not allowed | required | required | no |
externalId | required | required | not allowed | not allowed | yes, as id of adjunct if external |
roles | optional | optional | optional | optional | as IIIF auth |
creator | optional | optional | optional | optional | no |
source | optional | optional | optional | optional | no |
publicId | ignored | ignored | ignored | ignored | The IIIF id |
size | recommended | recommended | ignored | ignored | yes, as IIIF P4 property fileSize |
iiifLink | required | required | required | required | as linking property |
motivation | nb** | nb** | nb** | nb** | as annotation property |
provides | nb** | nb** | nb** | nb** | as annotation property |
- * must match other fields
- ** Only used when
iiifLinkis"inlineAnnotation"