authorIDy: Listing Contributions by Contributor Identifier

Warning: Discussion document - Not a specification (yet)
This version, created 20240224: https://signposting.org/authorIDy/
Check out the experimental demonstration of the authorIDy interface as described in this document
Please provide feedback in the GitHub Signposting repository, using label authorIDy
Increasingly, repositories allow, recommend, or require providing unique contributor identifiers, such as ORCID or ISNI, when depositing contributions. Despite this evolution, few repositories provide a machine interface that allows listing the contributions made by a researcher using their contributor identifier as a key. An interface with this capability, supported across repositories, would facilitate a range of use cases and could be an important next step towards realizing COAR’s Next Generation Repositories vision. This document describes core characteristics of authorIDy, a conceptual proposal for such a machine interface. Hopefully, this description will evolve into a specification.
Signposting the Scholarly Web: authorIDy

Image courtesy of Patrick Hochstenbach.



"authorIDy: a so simple protocol that could actually work." - Andrea Bollini of 4Science in a tweet during a presentation about authorIDy at Open Repositories 2024.

Make it so!

Table of Contents

  1. Motivation
  2. Design Principles
  3. Protocol Request
  4. Protocol Response
  5. Interface Discovery
  6. Possible authorIDy JSON Response Body
  7. JSON Schema for Possible authorIDy Response Body
  8. OpenAPI Description for Proposed authorIDy Interface

1. Motivation

The following motivate the work on authorIDy:

2. Design Principles

These are proposed design principles for a possible authorIDy interface:

3. Protocol Request


Requirement Purpose Request syntax
mandatory all contributions baseURL-service/*/contributor-id-uri/, e.g. <https://mirepo.org/createdby/*/https://orcid.org/1234-5678-1234-5678>
optional contributions since baseURL-service/yyyymmdd/contributor-id-uri/, e.g. <https://github.com/byuser/20231107/https://github.com/phonedude/>

4. Protocol Response

4.1. Protocol Response HTTP Header

A request may yield a paged response, in which case each individual response uses the HTTP Link header to link to previous and/or next portions of the response.


HTTP header Requirement Value
HTTP status code mandatory For successful requests: 200 OK. For unsupported requests (i.e. no support for the optional "contributions since" request) and malformed requests (e.g. 3-digit date): 400 Bad Request. For unknown contributor identifiers: 404 Not Found
Content-Type mandatory application/json
Link mandatory for paged response links with rel="prev" and/or rel="next" and type="application/json" to point at previous/next contributions

4.2. Protocol Response Body

Each response body is a JSON document consisting of a single header followed by a list of entries, one entry per contribution.

4.2.1. Single Header for an Entire Response Body

Property Requirement Cardinality Data Type Content
contributor mandatory [1] HTTP URI contributor identifier URI
4.2.2. Content for an Entry in a List of Contributions

Property Requirement Cardinality Data Type Content
contribution-page mandatory [1] HTTP URI URI of contribution, e.g. landing page URI
accession-date mandatory [1] ISO8601 date, Complete date format repository accession date
publication-date optional [0,1] ISO8601 date, Year format publication date
cite-as optional [0,1] HTTP URI persistent identifier URI (redirects to landing page URI)
contributor-type optional [0,n] HTTP URI contributor type URI from vocabulary, e.g. https://credit.niso.org/
contribution-type optional [0,n] HTTP URI contribution type URI from vocabulary, e.g. https://vocabularies.coar-repositories.org/resource_types/

5. Interface Discovery

The following paths can be be pursued:

6.Possible authorIDy JSON Response Body

Sample authorIDy Response Body with required properties only
{
  "contributor": "https://orcid.org/1234-5678",
  "contributions": [
    {
      "contribution-page": "https://mirepo.org/item/9876",
      "accession-date": "2023-01-04"
    },
    {
      "contribution-page": "https://mirepo.org/item/5432",
      "accession-date": "2022-03-20"
    }
  ]
}
Sample authorIDy Response Body including optional properties
{
  "contributor": "https://orcid.org/1234-5678",
  "contributions": [
    {
      "contribution-page": "https://mirepo.org/item/9876",
      "accession-date": "2023-01-04",
      "publication-date": "2022",
      "cite-as": "https://doi.org/12.9876",
      "contributor-type": [
        "https://credit.niso.org/contributor-roles/writing-original-draft/",
        "https://credit.niso.org/contributor-roles/software/"
      ],
      "contribution-type": [
        "https://vocabularies.coar-repositories.org/resource_types/c_6501/",
        "https://vocabularies.coar-repositories.org/resource_types/c_c950/"
      ]
    },
    {
      "contribution-page": "https://mirepo.org/item/5432",
      "accession-date": "2022-03-20",
      "publication-date": "2021",
      "cite-as": "https://doi.org/84.47562",
      "contributor-type": [
        "https://credit.niso.org/contributor-roles/writing-original-draft/"
      ],
      "contribution-type": [
        "https://vocabularies.coar-repositories.org/resource_types/c_6501/"
      ]
    }
  ]
}

7. JSON Schema for Possible authorIDy Response Body

Sample JSON Schema for authorIDy Response Body
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$id": "https://signposting.org/authorIDy/schema.json",
  "title": "authorIDy",
  "description": "An authorIDy response body",
  "type": "object",
  "properties": {
    "contributor": {
      "description": "contributor identifier URI",
      "type": "string",
      "pattern": "http(s)?://.*"
    },
    "contributions": {
      "description": "list of entries, one entry per contribution",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contribution-page": {
            "description": "URI of contribution, e.g. landing page URI",
            "type": "string",
            "pattern": "http(s)?://.*"
          },
          "accession-date": {
            "description": "repository accession date",
            "type": "string",
            "pattern": "\\d{4}-[01]\\d-[0-3]\\d"
          },
          "publication-date": {
            "description": "publication date",
            "type": "string",
            "pattern": "\\d{4}"
          },
          "cite-as": {
            "description": "persistent identifier URI (redirects to landing page URI)",
            "type": "string",
            "pattern": "http(s)?://.*"
          },
          "contributor-type": {
            "description": "contributor type URI from vocabulary, 
                            e.g. https://credit.niso.org/",
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "http(s)?://.*"
            }
          },
          "contribution-type": {
            "description": "contribution type URI from vocabulary, 
             e.g. https://vocabularies.coar-repositories.org/resource_types/",
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "http(s)?://.*"
            }
          }
        },
        "required": [
          "contribution-page",
          "accession-date"
        ]
      },
      "minItems": 1
    }
  },
  "required": [
    "contributor",
    "contributions"
  ]
}

8. OpenAPI Description for Proposed authorIDy Interface

Sample OpenAPI Description for authorIDy Interface
{
    "openapi": "3.0.3",
    "info": {
        "description": "This is mirepo's authorIDy instance",
        "version": "v1.0",
        "title": "mirepo authorIDy",
        "termsOfService": "https://mirepo.org/terms-of-service/",
        "contact": {
            "email": "admin@mirepo.org"
        },
        "license": {
            "name": "AGPL v3",
            "url": "https://www.gnu.org/licenses/agpl-3.0.en.html"
        }
    },
    "servers": [
        {
            "url": "https://mirepo.org/authorIDy",
            "description": "The production authorIDy server"
        }
    ],
    "paths": {
        "/*/{contributorID}": {
            "get": {
                "description": "Retrieve all contributions for a specified contributor identifier.",
                "parameters": [
                    {
                        "name": "contributorID",
                        "in": "path",
                        "description": "The HTTP identifier of a contributor",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "http(s)?://.*"
                        },
                        "style": "simple"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful operation",
                         "headers": {
                           "Link": {
                            "schema": {
                              "type": "array",
                                "items": {
                                  "type": "string"
                                 },
                            "example": 
                              "<http://service/{sinceDate}/{contributorID}?page=0> 
                                   ; rel=\"prev\",
                               <http://service/{sinceDate}/{contributorID}?page=2> 
                                   ; rel=\"next\""
                              },
                             "required": false,
                             "description": "Optional links to next or previous pages (or both)"
                             }
                        },
                        "content": {
                            "application/json":
                            {
                              "schema":
                               {
                               "$ref": "https://signposting.org/authorIDy/authorIDy_schema.json"
                               }
                            }
                         }
                    },
                    "404": {
                        "description": "Unknown contributor identifier"
                    }
                }
            }
        },
        "/{sinceDate}/{contributorID}": {
            "get": {
                "description": "Retrieve contributions since and including 
                 an accession date (yyyymmdd) for a specified contributor identifier.",
                "parameters": [
                    {
                        "name": "contributorID",
                        "in": "path",
                        "description": "The HTTP identifier of a contributor",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "http(s)?://.*"
                        },
                        "style": "simple"
                    },
                    {
                        "name": "sinceDate",
                        "in": "path",
                        "description": "The accession date in yyyymmdd format",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "pattern": "\\d{4}\\d{2}\\d{2}"
                        },
                        "style": "simple"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Successful operation",
                         "headers": {
                           "Link": {
                            "schema": {
                              "type": "array",
                                "items": {
                                  "type": "string"
                                 },
                            "example": 
                              "<http://service/{sinceDate}/{contributorID}?page=0> 
                                   ; rel=\"prev\",
                               <http://service/{sinceDate}/{contributorID}?page=2> 
                                   ; rel=\"next\""
                              },
                             "required": false,
                             "description": "Optional links to next or previous pages (or both)"
                             }
                        },
                        "content": {
                            "application/json":
                            {
                              "schema":
                               {
                               "$ref": "https://signposting.org/authorIDy/authorIDy_schema.json"
                               }
                            }
                         }
                    },
                    "404": {
                        "description": "Unknown contributor identifier"
                    },
                    "400": {
                        "description": "Date in yyyymmdd format required."
                    }
                }
            }
        }
    }
}