Annotations API

The Annotations API is an extension to the Europeana REST API which allows for the management, retrieval and discovery of annotations.

To get straight to the point of the API, you can go directly to the Getting Started section which tells you only what you have to know to start using the API.

What are Annotations?

Annotations (in the Europeana context) are user-contributed or system-generated enhancements to (a selection of) metadata or media. The most well-known type of annotation is the "tag", a short textual depiction of something. Annotations allow for the creation of meaningful connections across Europeana and will also offer up new ways to explore or find the content you're looking for.

Background on the API

The Annotations API was initially developed as part of the Europeana Sounds project. The development work is carried out by the AIT Austrian Institute of Technology in cooperation with the Europeana Foundation.

Roadmap and changelog

For an overview of what we're working on you can take a look at our Roadmap and Changelog section.

Discussion

Join the Europeana API discussion group at Google Groups and get regular updates about the Europeana API, provide feedback and discuss it with other developers.

Terms of Use

Please see here our Terms of Use.

Annotation Data Model

The Annotations API adopted the Web Annotation Data Model as a base model for representing and exchanging annotations between client applications and the API.

Background

The Web Annotation Data Model (or simply WA) describes a model and format to share annotations across different platforms. It is currently a W3C proposal based on the work of the Open Annotation Community and working towards becoming a W3C recommendation. Due to early stage of development it may be expected to suffer changes in the future which may impact this API.

Please note that, even though we have adopted WA as underlying data model for this API, it is not expected that we support the full extent of the model. We thus advise to look at the section on Annotation Scenarios for a comprehensive list of the different kinds of annotations that we support.

Basics of the model

In WA, an annotation is essentially a reified relation between two or more resources, typically a body and a target, and conveys that the body reflects what is intended to be said about the target. A body can also be absent to describe situations where a target is simply bookmarked. A target can represent a resource or just a part of it that is being annotated.

Being reified as a class enables an annotation to be further described with a motivation which expresses the reason why the annotation was created but also some provenance information such as the user that created the annotation and the software application that was used, as well as the times when it was initially created and sent to the API.

Representation in JSON-LD

Annotation

FieldDatatypeDescription
@contextString (URL)The URL of the JSON-LD context. (always with value "http://www.w3.org/ns/anno.jsonld")
idString (URI)The identifier of the Annotation. It is automatically generated unless a local identifier is specified upon creation.
typeStringAlways has the values of "Annotation".
createdString (DateTime)The time at which the Annotation was created by the client application. It must be expressed in ISO8601 format and should have a timezone specified.
creatorObject (Agent)The agent responsible for creating the Annotation. This may be either a human or software agent.
generatedString (DateTime)The time at which the annotation was sent to the server.
generatorObject (Software)The agent responsible for generating the Annotation. Typically a client application used to create the annotation.
motivationStringExpresses the reason why the annotation was created. The value can be either "tagging" or "linking".
bodyString or Object (Semantic Resource or Textual Body)A body conveying what is intended to be said about the target. If the value is provided as a string, then it is interpreted as the URI and must only be used for the semantic tagging scenario. See the application scenarios section for more information.
bodyValueStringA string conveying the tag text. This field must only be used in combination with "tagging" as motivation and when the language of the tag is not known. Otherwise, it is recommended to use the body field as defined in the Application Scenarios section.
targetString or Array (String)The URL of the resource that is being annotated. An array of URLs may also be set (mostly used for the object linking).

Agent

An Agent can be either a Person or a Software. Typically the Person corresponds to the user that created the annotation while the Software reflects the client application that was used to create it. A Software can also create annotations if they result from an automatic process.

FieldDatatypeDescription
typeStringEither "Person" or "Software".
nameStringThe name of the agent. Either the name of the user that created the annotation, or the name of the client software that was used to create it.
homepageStringThe homepage of the user or client application, if available.

Semantic Resource

A Semantic Resource is used whenever an external resource needs to be referenced as the body of the annotation. It is mostly used for Semantic Tagging.

FieldDatatypeDescription
typeStringAlways "SpecificResource.
sourceString (URI)The URI of the resource being referred as body.
languageString (ISO639)The ISO639 language code corresponding to the language of the resource.

Optional and mandatory fields

FieldPOSTPUTDELETEREAD
@contextOMN/AM
idOMN/AM
typeOMN/AM
createdOMN/AM
creatorMMN/AM
generatedOMN/AM
generatorOMN/AM
motivationMMN/AM
bodyOM (either body or bodyValue)N/AM (either body or bodyValue)
bodyValueOM (either body or bodyValue)N/AM (either body or bodyValue)
targetMMN/AM

Example:

{
  "@context": “http://www.w3.org/ns/anno.jsonld”
  "id": "http://data.europeana.eu/annotations/1",
  "type": "Annotation",
  "created": "2015-03-10T14:08:07Z",
  "creator": {
    "type": "Person",
    "name": "John Smith"
  },
  "generated": "2015-04-01T09:00:00Z",
  "generator": {
      "type": "Software",
      "name": "HistoryPin",
      "homepage": "https://www.historypin.org/"
  },
  "motivation": "tagging",
  "bodyValue": "MyBeautifulTag",
  "target": "http://data.europeana.eu/item/92062/BibliographicResource_1000126189360"
}

Annotation Scenarios

The Annotations API supports different types of annotations. This section explains the types of annotations that are currently supported, providing examples on how to represent them in the API.

1. Simple tags (without language)

A simple tag is a short textual description of a resource. This scenario only applies when the language of the tag is not know, otherwise see the scenario described in the next Section.

Examples:church
blue
black and white
Requirement:A maximum of 64 characters is allowed for a simple tag.
A tag cannot be a URL.
In the API:Set the "motivation" to "tagging" and set the tag within the "bodyValue" field.
Availability:Simple tags are available since version 0.2.1.

Example 1:

The example below is a shortened version of the Annotation, see the complete version on Data Model.

{
  "motivation": "tagging",
  "bodyValue": "painting",
  "target": "http://data.europeana.eu/item/92062/BibliographicResource_1000126189360"
}

2. Simple tags (with language)

A simple tag is a short textual description of a resource.

Examples:church
blue
black and white
Requirement:A maximum of 64 characters is allowed for a simple tag.
A tag cannot be a URL.
The language information must be specified.
In the API:Set the "motivation" to "tagging" and set the tag within the "body" field as a Textual Body.
Availability:Simple tags are available since version 0.2.1.

Example 2:

The example below is a shortened version of the Annotation, see the complete version on Data Model.

{
  "motivation": "tagging",
  "body": {
    "type": "TextualBody",
    "value": "painting",
    "language": "en"
 },
  "target": "http://data.europeana.eu/item/92062/BibliographicResource_1000126189360"
}

Semantic tags

A semantic tag is a tag to a resource from a controlled vocabulary, making it machine-interpretable.

Example:This object in Europeana is somehow related to France (http://sws.geonames.org/2988507).
Requirement:Any URI is accepted as semantic resource. In the future, it will be limited to a controlled list of acceptable domains.
In the API:Set the "motivation" to "tagging" and set as body the URI for the semantic resource taken from a contolled vocabulary.
Availability:Semantic tags are available since version 0.2.1.

Example 4:

The example below is a shortened version of the Annotation, see the complete version on Data Model.

{
  "motivation": "tagging",
  "body": "http://sws.geonames.org/2988507",
  "target": "http://data.europeana.eu/item/09102/_UEDIN_214"
}

Object links

An object link is a relationship between two (Europeana) objects. This relationship can be any.

Example:This object in Europeana is (in some way) similar to this object.
Requirement:An object link can only be made between two Europeana objects.
In the API:Set the "motivation" to "linking" and set as target an array containing the URIs of both objects.
Availability:Object linking is available since version 0.2.1.

Example 5:

The example below is a shortened version of the Annotation, see the complete version on Data Model.

{
  "motivation": "linking",
  "target": [
      "http://data.europeana.eu/item/92062/BibliographicResource_1000126189360",
      "http://data.europeana.eu/item/92062/BibliographicResource_1000126189361"
  ]
}

Geo-tags

A geo-tag adds a geographical location to an item.

Example:This object in Europeana was located at latitude 52.081131 and longitude 4.324053. .
In the API:Set the "motivation" to "tagging" and include the "type", "lat" and "long" attributes in the body as per the example below.
Availability:Object linking is available since version 0.2.2.

Example 6:

{
  "motivation": "tagging",
  "body": {
    "@context": "http://www.europeana.eu/schemas/context/entity.jsonld",
    "type": "Place",
    "lat": "52.081131",
    "long": "4.324053"
  },
  "target": "http://data.europeana.eu/item/92034/GVNRC_NFA03_kop_6_3"
}

Getting started

API keys

While the Annotations API is in an Alpha state you will need to use a separate API key (other than for the main REST API) to start experimenting with the Annotations API. You can use the following keys:

  • Test environment: API key apidemo with user token tester1 (allows to create, update & remove annotations on behalf of a test user in the Annotations API test environment).
  • Production environment: API key apidemo (allows to search and retrieve annotations in the Annotations API production (live) environment).

Creating annotations in the production (live) environment is currently limited to only selected partners, this will be opened up as part of the Beta release.

Request

Every Annotations API call is an HTTP request in a specified format that is sent to the Annotations API service. The API root URLs for the two environments are located at:

https://test-annotations.europeana.eu/annotation (test)
https://www.europeana.eu/api/annotations (production)

Response format

The Annotations API currently only supports the JSON-LD format, which is the Linked Open Data version of JSON (with the same syntax as JSON). The request and response format does not need to be passed along to the API, if not provided it will fallback to the default. You can provide the format either via the URL (extension) or via the "Accept" header. To specify the request and response format you can either do:

search.jsonld?wskey=xxxxx&query=*:*

Or:

Request header: "Accept: application/ld+json"
search?wskey=xxxxx&query=*:*

Authentication

To authenticate your API client against the Annotations API for reading (GET requests) you need to pass along your API key as the wskey parameter. Example (replace xxxxxx with your API key):

search?wskey=xxxxx&query=*:*

To authenticate your API client against the Annotations API for writing (POST/PUT/DELETE requests) on behalf of a user you need to pass along your API key as the wskey parameter along with a user token as the userToken parameter. Example (replace xxxxxx with your API key and yyyyy with the user token):

create?wskey=xxxxx&userToken=yyyyy&query=*:*

HTTP Response Codes

All successful responses return with a 2XX code. In the event of an error during processing of an API method, it is reported by (1) a relevant HTTP status code, (2) a value of the success field and (3) a meaningful error message in the error field.

The following HTTP status codes are returned:

HTTP Status CodeDescription
200The request was executed successfully.
401Authentication credentials were missing or authentication failed.
404The requested annotation was not found.
429The request could be served because the application has reached its usage limit.
500Internal Server Error. Something has gone wrong, which we will correct.

API methods

Search for annotations.

Request

GET /search?query=QUERY&profile=PROFILE&qf=QF&facet=FACET&pageSize=PAGE_SIZE&page=PAGE&sort=SORT&sortOrder=SORT_ORDER
ParameterDatatypeDescription
queryStringThe search term(s), this is mandatory.
profileStringThe search profile which determines the extent of information returned as search result. Currently, two options are supported: "minimal" which returns only the identifier of the annotation; and "standard" (the default) which returns the annotation as it was sent to the API.
qfStringQuery filter, to search on specific fields. The list of fields is presented below.
facetStringIncludes a field to be used as facet in the response (see below which fields can be used as facets). More than one field can be added if separated by a space.
pageSizeNumberThe number of records to return per page. For minimal profile, the maximum is 10.000 while for the standard profile is 100, with 10 as default for both profiles.
pageNumberThe page of the search results, defaults to 0 (first page).
sortStringIncludes a field to be used for sorting. One of: created, generated or modified.
sortOrderStringOrder of sorting, either "asc" (ascending) or "desc" (descending).

Search and Facet fields

The following table shows the fields that can be used for searching annotations and the ones that can be used for faceting:

FieldDatatypeUsed for FacettingDescription
motivationkeywordyesmotivation of the Annotation
anno_urikeywordcomplete identifier of an Annotation
anno_idkeywordlocal identifier of an Annotation (/<provider>/<identifier>)
generator_urikeywordyescomplete identifier of the generator
generator_namekeywordyesname of the generator
generateddatedate on which the Annotation was first provided to the API
creator_urikeywordyescomplete identifier of the creator
creator_namekeywordyesname of the user that created the annotation
createddatedate on which the Annotation was created by the annotation client application
modifieddatedate on which the Annotation was last modified
moderation_scoreintegeryessum of all reports made to an Annotation by other users
texttextsearches in all searchable text in an Annotation
body_valuetextyesvalue within the body of an Annotation, applies to e.g. simple tagging
body_urikeywordyescomplete identifier of the resource within the body of an Annotation, applies to e.g. semantic tagging
target_urikeywordyescomplete identified of the target(s) of an Annotation
target_record_idkeywordyeslocal identifier of a record when the target is a record (/collectionId/objectId)
link_resource_urikeywordyescomplete identifier of the resource being linked to (ie. through the relation property)
link_relationkeywordyesproperty being used to link two resources.

Examples

Search for recently added tags:

/search?wskey=xxxxx&profile=minimal&query=*:*&qf=motivation:tagging&sort=created&sortOrder=desc

Search for tags for Europeana record ID /92028/532E53363138382D2F290A40B3CA26B3889A6907:

/search?wskey=xxxxx&profile=minimal&query=target_id:"/92028/532E53363138382D2F290A40B3CA26B3889A6907"

Don't show annotations which are reported by two or more different users:

/search?wskey=xxxxx&profile=minimal&query=*:*&qf=moderation_score:[-1 TO *]

Note that providing *:* as a search query means you will get all annotations.

Response

{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "http://annotations.europeana.eu/annotation/search?wskey=xxxxx&query=*:*&page=0&pageSize=10",
  "items": [
    "http://data.europeana.eu/annotation/base/1",
    "http://data.europeana.eu/annotation/base/2",
    [..]
  ],
  "next": "http://annotations.europeana.eu/annotation/search?wskey=xxxxx&query=*:*&page=1&pageSize=10",
  "partOf": {
     "id": "http://annotations.europeana.eu/annotation/search?wskey=xxxxx&query=*:*",
     "total": 135610
  },
  "total": 10,
  "type": "AnnotationPage"
}

Create

The Annotations API has a generic method available for the creation of annotations. The creation method expects a body payload in the request with the full annotation. Alternatively you can provide this information as part of the body parameter.

POST http://annotations.europeana.eu/annotation/

Request

An example to create a simple tag:

POST /annotation/?wskey=xxx&userToken=yyy HTTP/1.1
Accept: application/ld+json
Content-Type: application/ld+json
Content-Length: 999
{
  "motivation": "tagging",
  "bodyValue": "Trombone",
  "target": "http://data.europeana.eu/item/09102/_UEDIN_214"
}

Note that the motivation for a simple and a semantic tag is always "tagging", whereas the motivation for object linking scenarios is "linking".

Response

Response to the example request:

Content-Type: application/ld+json
ETag: "_87e52ce126126"
Link: <http://www.w3.org/ns/ldp#Resource>l; rel="type"
Allow: POST,GET,OPTIONS,HEAD
Vary: Accept
Content-Length: 999
{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "http://data.europeana.eu/annotation/base/1",
  "type": "Annotation",
  "created": "2016-01-31T12:03:45Z",
  "creator": "http://data.europeana.eu/user/55376",
  "generated": "2016-01-31T12:04:00Z",
  "generator": "http://data.europeana.eu/provider/historypin",
  "bodyValue": "Trombone",
  "motivation": "tagging",
  "target": "http://data.europeana.eu/item/09102/_UEDIN_214"
}

For more examples and information on the data model for an annotation, see data model.

Read

Retrieve annotations by their identifier.

GET /{provider}/{identifier}

Request

Response

HTTP/1.1 200 OK
Content-Type: application/ld+json
{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "http://data.europeana.eu/annotation/base/1",
  "type": "Annotation",
  "created": "2016-01-31T12:03:45Z",
  "generated": "2016-01-31T12:04:00Z",
  "generator": "http://www.europeana.eu",
  "bodyValue": "Trombone",
  "motivation": "tagging",
  "target": "http://data.europeana.eu/item/09102/_UEDIN_214"
}

See data model for more information on the representation of an annotation.

Update

Update the contents of an annotation. For this you can send a PUT request to the ID of the annotation. You can only update the annotations you have created yourself.

PUT /base/1

Request

You can provide the same contents as for the creation of annotations. Note that you have to provide the full annotation body, you currently cannot update parts of the annotation.

PUT /base/1 HTTP/1.1
Accept: application/ld+json
{
  "bodyValue": "Trombone",
  "motivation": "tagging",
  "target": "http://data.europeana.eu/item/09102/_UEDIN_214"
}

Response

HTTP/1.1 200 OK
Content-Type: application/ld+json
{
  "@context": "http://www.w3.org/ns/anno.jsonld",
  "id": "http://data.europeana.eu/annotation/base/1",
  "type": "Annotation",
  "created": "2016-01-31T12:03:45Z",
  "generated": "2016-01-31T12:04:00Z",
  "generator": "http://www.europeana.eu",
  "bodyValue": "Trombone",
  "motivation": "tagging",
  "target": "http://data.europeana.eu/item/09102/_UEDIN_214"
}

Delete

Delete an annotation. For this you can send a DELETE http request using the ID of the annotation. You can only delete the annotations you have created yourself. Deletion means the annotation will not be available anymore for search, and only available for retrieval based on the ID of the annotation.

DELETE /base/1

Request

DELETE /collections/1 HTTP/1.1

Response

HTTP/1.1 204 NO CONTENT
Content-Length: 0

Annotations API Console

Use the API Console to experiment with the API and build queries. The Request URL will display the call you need to make to the API. The console below points to the production environment, to use the API console for the test environment click here.

Roadmap

A roadmap for the development of the Annotations API

The Annotations API will work towards a first major release at the third quarter of 2017. Until then, the Annotations API will feature many updates and iterations, which will be listed on this page.

The contents of the roadmap are subject to change, they will be updated at least every three weeks.

Major releases

Alpha release: February 2016
Beta release: 3/4 2017
Stable release: Early 2018

In development
  • Enhancements to semantic tagging:
    • Support for more vocabularies.
    • Extracting and storing information from semantic resources (dereferencing).
  • Preparations for the Beta release:
    • Allow Europeana REST API keys to be used for the Annotations API.
    • Connect MyEuropeana API to the Annotations API for individual user management.
    • Automated registration of providers for annotations.
Planned development
  • Support for image (coordinates) annotations.
  • Support for time-based annotations (audio).
  • Support for geo-based annotations.
Along with the planned features every new release will aim to improve existing features, enhance existing types of annotations and to incorporate feedback from developers and users.

Change Log

Version 0.2.7 (May 2017)

In this release we have:

  • added support for the search profiles
  • adjusted pageSize limits for search to make them configurable and profile dependent
  • made several improvements to exception handling: responding with proper error codes and understandable error messages that can be configured through property files.
  • migrated the provider and user configurations to MongoDB.
  • revised the fields used for search and faceting, and fixed some issues.
  • fixed the PUT method to be less restrictive.
  • added support for asynchronuous indexing.
  • added support for canonical identifiers
  • added a method to support the update all references to record identifiers following changes in the main Europeana reference database
  • added support for write locks to the API for maintenance purposes.

Version 0.2.6 (December 2016)

In this release we have:

  • Removed the (Java) Exception class from error messages, all error messages only show what's happening in friendly ways now.
  • Updated the logic of the "generator" class in annotations. The minimised version (single value) can contain both a name or URI. The expanded version can contain an "id" (must be a URI) and/or "name" property.

Version 0.2.5 (October 2016)

In this release we mostly fixed some bugs:

  • Fixed a bug where the "items" listing in the search method did return a string for single-item results instead of a list.
  • Allowed Cross-Origin Domain requests to the Swagger API spec, to power the Annotations API console.
  • Added utf-8 headers to all JSON-LD output to ensure response is properly formatted.
  • Fixed a bug where requesting facets could return an exception.

Version 0.2.4 (October 2016)

In this release we've updated the API specification in line with the latest Candidate Recommendation release of the Web Annotations Protocol. This means that in the search method, many fields and structures have changed which are not backwards compatible. The good news is that since the latest protocol is a Candidate Recommendation, this should be the last Major change which breaks backwards compatibility.

  • Renamed the "contains" field to "items".
  • Add an "isPartOf" element to the search output to indicate information about the search result set with the total number of items ("total") and the URI of the search query ("id").
  • Changed the value of "type" to "AnnotationPage".
  • Added support for "next" and "prev" in the search output to indicate the URIs for the next and previous pages of search results (if applicable).
  • Added an "id" field to the search output with the URI of the search results (first page).
  • Renamed "totalItems" to "total" with the number of items on the current search result page (the total number of search results is in "total" in the "isPartOf" element.
  • To control the number of search results per page, use the "pageSize" parameter (defaults to 10).
  • To control the page (to paginate), use the "page" parameter, which defaults to 0 (first page).

Version 0.2.3 (August 2016)

In this release we have improved our search for annotations, which allows you to search for other fields than those were already available. We also updated some of the names of the search fields.

  • New: the ability to search for annotations based on the generator (id and name, fields: generator_id, generator_name).
  • Change: updated the fields for target_record_ids to target_id and motivation_key to motivation. This applies to both search & faceting.

Version 0.2.2 (July 2016)

With this release we further stabilised the Annotations API and addressed some feedback from the Alpha version. This version is a further iteration of the Public Alpha.

New features:

  • Support for geo-tagging, you can now submit geo-tags to the Annotations API for geographical information.

We've also updated our API to reflect the latest updates on the Web Annotation Model. Make sure to update your API clients accordingly:

  • The @ has been removed from all fields except for @context.
  • The simple tagging scenario without language information should use the bodyValue field to represent the tag. You can no longer send a literal as body anymore in this scenario.
  • The semantic tagging scenario does now accept a URI resource directly in the body field.
  • The annotation type has been updated from oa:Annotation to just Annotation.

Version 0.2.1 (March 2016)

First Public Alpha version of the Annotations API. Alpha means that the API is available for preview and testing. This also means that while the API is in Alpha changes can be and are likely to be made which are not backwards compatible.

  • First release.
  • Support for simple tags, semantic tags and object links.
top