diff --git a/.github/scripts/validate_files.py b/.github/scripts/validate_files.py index 4f9daec..413d15c 100644 --- a/.github/scripts/validate_files.py +++ b/.github/scripts/validate_files.py @@ -16,7 +16,7 @@ def get_pushed_files(): - return [f"./{file}" for file in changed_files if file.endswith(".json")] + return [f"./{file}" for file in changed_files if ( file.endswith(".json") and not file.endswith("skg-if-api.json") ) ] def validate_file(file_path): diff --git a/index.md b/index.md index 9d997b1..35defc2 100644 --- a/index.md +++ b/index.md @@ -7,21 +7,154 @@ nav_order: 7 # API Specifications {: .highlight } -**Work in progress**: The WG agreed with RDA a 6-month deadline extension (i.e., end of June 2025) in order to deliver full-fledged API specifications that go beyond the "vanilla" resolvers describe in the first iteration of the SKG-IF. We opted for **OpenAPI** to describe the endpoints and the format of the objects to exchange on the wire; the *ALPHA* specifications are shared below. For the sake of completeness, you can check our working document on API development [here](https://docs.google.com/document/d/1t7b7h28UTtM56Sda4NGJIp0hnQfGbcVVGn12fny9wfI/edit?tab=t.0#heading=h.hso3muyqtlhx). +## Versions -The current (i.e., last) version of the SKG-IF OpenAPI specifications is available at [https://w3id.org/skg-if/api/skg-if-openapi.yaml](https://w3id.org/skg-if/api/skg-if-openapi.yaml). +**OpenAPI** is used to describe the endpoints and the format of the objects to exchange on the wire, the specifications are shared below. +For the sake of completeness, you can also check the [SKG-IF OpenAPI Implementer documentation](https://docs.google.com/document/d/1t7b7h28UTtM56Sda4NGJIp0hnQfGbcVVGn12fny9wfI/edit?tab=t.0#heading=h.hso3muyqtlhx). -One can access the OpenAPI specifications of all (current and previous) versions by using a version number in the `w3id.org` URL, before the name of the YAML file, following this pattern: +* The current (i.e., last) version of the SKG-IF OpenAPI specifications is available at [https://w3id.org/skg-if/api/skg-if-openapi.yaml](https://w3id.org/skg-if/api/skg-if-openapi.yaml). +* One can access the OpenAPI specifications of all (current and previous) versions by using a version number in the `w3id.org` URL, following this pattern: +`https://w3id.org/skg-if/api//skg-if-openapi.yaml`. For instance: `https://w3id.org/skg-if/api/1.0.0/skg-if-openapi.yaml` allows to access to version 1.0.0 of the SKG-IF OpenAPI specifications. + +The SKG-IF OpenAPI version, present in the YAML, is independent from the SKG-IF Data model version. + +``` yaml +openapi: 3.1.0 +info: + version: 1.0.0 + title: SKG-IF OpenAPI - compatible with SKG-IF Data Model 1.1.0 + + ... + "@context": + "https://w3id.org/skg-if/context/1.1.0/skg-if.json", // Fixed SKG-IF data model context + "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", // Fixed SKG-IF API context + { + "@base": "https://w3id.org/skg-if/sandbox/acme/" + } + ... + +``` + +## Viewers + +You can also visualize the OpenAPI specifications with standard tools like : + +* Stoplight : [https://elements-demo.stoplight.io/?spec=https://w3id.org/skg-if/api/skg-if-openapi.yaml](https://elements-demo.stoplight.io/?spec=https://w3id.org/skg-if/api/skg-if-openapi.yaml) +* Swagger : [https://editor.swagger.io/?url=https://w3id.org/skg-if/api/skg-if-openapi.yaml](https://editor.swagger.io/?url=https://w3id.org/skg-if/api/skg-if-openapi.yaml) + + +## Define your @base + +`@base` is a default prefix domain fallback for all identifiers not defined as URLs in the `@graph` +A `local_identifier` value, when not starting with “http”, is interpreted by concatenation to the `@base`. + +For the `local_identifier` domain (your `@base`), you have a few options for the ACME organisation. + +* Use `https://w3id.org/skg-if/sandbox/acme/` . We don’t recommend it for prod because it does not resolve anywhere ( related to the ACME organisation ) +* Define a [w3id.org](https://w3id.org) domain ex: `https://w3id.org/acme/` . You can set up w3id.org to redirect to your catalogue. ex: `https://w3id.org/acme/prod-1` => `https://www.acme.com/product-catalogue/prod-1` +* Use a graph dedicated domain you already have ex: `https://www.acme.com/theskg/`, `https://www.acme.com/theprodgraph/` + +Make sure that you generate distinct URLs ids for person, product... They should not conflict. + +## Endpoints and JSON-LD output + +* The SKG-IF OpenAPI defines 2 types of endpoints + * Get _Entity_ by Id + * Get List of _Entity_ +* The SKG-IF OpenAPI endpoints outputs are JSON-LD and compatible with the [SKG-IF data model](https://skg-if.github.io/interoperability-framework/) + +## API links + +* The `@graph` array contains entities, identified by their `local_identifier`, each entity may have relation to other entities also identified by their `local_identifier`. +* From a client perspective, if the sub entity is not embedded with its fields, you may need to perform sub queries to access these fields. +* The JSON-LD output contains a `meta` section SHOULD provide you API links for each entity, identified by its `local_identifier`. As a client you are not supposed to guess the API URL from the `local_identifier` format, there is no standard for the API domain prefix, each implementer is free to have a domain for its `local_identifier` and another one for its API (It is even recommended). + + +Get Product by Id : `https://acme.com/skg-if/api/products/prod-1` + +``` json +{ + "meta" : { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1", // parent local_identifier / PID + "entity_type": "single_entity", + "api_items": [ + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1", // local_identifier / PID + "urls": [ + { + "entity_type": "link", + "rel": "self", + "href": "https://acme.com/skg-if/api/persons/pers-1" // API link + } + ] + } + ] + }, + "@graph": [ + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1", + "contributions": [ + { + "by" : { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1" + //... + } + //... + } + ] + //... + } + ] +} ``` -https://w3id.org/skg-if/api//skg-if-openapi.yaml + +Get List of Product : `https://acme.com/skg-if/api/products?filter=xxx&page=1` + +``` json +{ + "meta": { + "local_identifier": "https://acme.com/skg-if/api/products?filter=xxx&page=1", // search identifier, API link + "entity_type": "single_entity", + "api_items": [ + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1", // local_identifier / PID + "urls": [ + { + "entity_type": "link", + "rel": "self", + "href": "https://acme.com/skg-if/api/persons/pers-1" // API link + } + ] + } + ] + + }, + "@graph": [ + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1", + "contributions": [ + { + "by" : { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1" + //... + } + //... + } + ] + //... + }, + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1" + //... + }, + + ] +} + ``` -For instance: -* `https://w3id.org/skg-if/api/1.0.0/skg-if-openapi.yaml` allows to access to version 1.0.0 of the OpenAPI specifications; -* `https://w3id.org/skg-if/api/0.2.0/skg-if-openapi.yaml` allows to access to version 0.2.0 of the OpenAPI specifications; -* and so on. diff --git a/openapi/ver/1.0.0/context/skg-if-api.json b/openapi/ver/1.0.0/context/skg-if-api.json index e59988e..506793f 100644 --- a/openapi/ver/1.0.0/context/skg-if-api.json +++ b/openapi/ver/1.0.0/context/skg-if-api.json @@ -9,6 +9,9 @@ "search_result": { "@id": "as:Collection" }, + "single_entity": { + "@id": "as:Object" + }, "part_of": { "@id": "as:partOf" }, @@ -27,6 +30,24 @@ "prev_page": { "@id": "as:prev" }, - "meta": "@nest" + "meta": "@nest", + "api_items": { + "@id": "as:items", + "@container": "@set" + }, + "urls": { + "@id": "as:url", + "@container": "@set" + }, + "rel": { + "@id": "as:rel" + }, + "href": { + "@id": "as:href", + "@type": "@id" + }, + "media_type":{ + "@id": "as:mediaType" + } } } \ No newline at end of file diff --git a/openapi/ver/current/context/skg-if-api.json b/openapi/ver/current/context/skg-if-api.json index e59988e..f23cb87 100644 --- a/openapi/ver/current/context/skg-if-api.json +++ b/openapi/ver/current/context/skg-if-api.json @@ -9,6 +9,9 @@ "search_result": { "@id": "as:Collection" }, + "single_entity": { + "@id": "as:Object" + }, "part_of": { "@id": "as:partOf" }, @@ -27,6 +30,24 @@ "prev_page": { "@id": "as:prev" }, - "meta": "@nest" + "meta": "@nest", + "api_items": { + "@id": "as:items", + "@container": "@set" + }, + "urls": { + "@id": "as:url", + "@container": "@set" + }, + "rel": { + "@id": "as:rel" + }, + "href": { + "@id": "as:href", + "@type": "@id" + }, + "media_type":{ + "@id": "as:mediaType" + } } } \ No newline at end of file diff --git a/openapi/ver/current/sample_data/grants/grant_1.json b/openapi/ver/current/sample_data/grants/grant_1.json index 73daf2a..0440bdc 100644 --- a/openapi/ver/current/sample_data/grants/grant_1.json +++ b/openapi/ver/current/sample_data/grants/grant_1.json @@ -3,12 +3,12 @@ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", { - "@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + "@base": "https://w3id.org/skg-if/sandbox/acme/" } ], "@graph": [ { - "local_identifier": "http://example.com/skg-if/api/grants/6f368a3a-b1cf-498f-b2de-27135d1e0011", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/grant-1", "identifiers": [ { "scheme": "doi", @@ -25,7 +25,7 @@ }, "acronym": "GraspOS", "funding_agency": { - "local_identifier": "http://example.com/skg-if/api/organisations/org-xxx", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/org-1", "entity_type": "organisation", "identifiers": [ { @@ -48,7 +48,7 @@ "website": "https://graspos.eu", "beneficiaries": [ { - "local_identifier": "http://example.com/skg-if/api/organisations/xxx", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/org-1", "entity_type": "organisation", "identifiers": [ { @@ -65,7 +65,7 @@ "contributions": [ { "by": { - "local_identifier": "http://example.com/skg-if/api/persons/xxx", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1", "entity_type": "person", "identifiers": [ { @@ -79,7 +79,7 @@ }, "declared_affiliations": [ { - "local_identifier": "http://example.com/skg-if/api/organisations/xxx", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/org-1", "entity_type": "organisation", "identifiers": [ { diff --git a/openapi/ver/current/sample_data/organisations/org_brown_university.json b/openapi/ver/current/sample_data/organisations/org_brown_university.json index d1bc04e..3479d1b 100644 --- a/openapi/ver/current/sample_data/organisations/org_brown_university.json +++ b/openapi/ver/current/sample_data/organisations/org_brown_university.json @@ -3,12 +3,12 @@ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", { - "@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + "@base": "https://w3id.org/skg-if/sandbox/acme/" } ], "@graph": [ { - "local_identifier": "http://example.com/skg-if/api/organisations/6f368a3a-b1cf-498f-b2de-222222222", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/org-1", "entity_type": "organisation", "identifiers": [ { diff --git a/openapi/ver/current/sample_data/products/journal_article_full.json b/openapi/ver/current/sample_data/products/journal_article_full.json index c70f63f..2f93561 100644 --- a/openapi/ver/current/sample_data/products/journal_article_full.json +++ b/openapi/ver/current/sample_data/products/journal_article_full.json @@ -3,12 +3,48 @@ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", { - "@base": "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + "@base": "https://w3id.org/skg-if/sandbox/acme/" } ], + "meta": { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1", + "entity_type": "single_entity", + "api_items": [ + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1", + "urls": [ + { + "entity_type": "link", + "rel": "self", + "href": "https://acme.com/skg-if/api/products/prod-1" + } + ] + }, + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1", + "urls": [ + { + "entity_type": "link", + "rel": "self", + "href": "https://acme.com/skg-if/api/persons/pers-1" + } + ] + }, + { + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/venue-1", + "urls": [ + { + "entity_type": "link", + "rel": "self", + "href": "https://acme.com/skg-if/api/venues/venue-1" + } + ] + } + ] + }, "@graph": [ { - "local_identifier": "http://example.com/skg-if/api/products/614a6575-5d6c-416c-a8e1-ddd456d132", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/prod-1", "entity_type": "product", "product_type": "literature", "titles": { @@ -48,13 +84,13 @@ "scheme": "orcid" } ], - "local_identifier": "http://example.com/skg-if/api/persons/614a6575-5d6c-416c-a8e1-f49a5d589bf8", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/pers-1", "entity_type": "person" }, "declared_affiliations": [ { "name": "Center for Plant Biotechnology and Genomics, Universidad Politécnica de Madrid, Madrid, 28223, Spain", - "local_identifier": "http://example.com/skg-if/api/organisations/32bc66c6-38be-4d5f-85db-d44c9f86921f", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/org-1", "entity_type": "organisation", "country": "ES" } @@ -72,7 +108,7 @@ }, "biblio": { "hosting_data_source": { - "local_identifier": "http://example.com/skg-if/api/datasources/6f368a3a-b1cf-498f-b2de-27135d1e0075", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/datasource-1", "entity_type": "datasource", "name": "An Archive" }, @@ -85,7 +121,7 @@ "scheme": "issn" } ], - "local_identifier": "http://example.com/skg-if/api/venues/51f46bc1-00f8-42dd-8221-ac4deb52fb25", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/venue-1", "entity_type": "venue" } }, @@ -105,7 +141,7 @@ ], "funding": [ { - "local_identifier": "http://example.com/skg-if/api/grants/614a6575-5d6c-416c-a8e1-f49a5d58999", + "local_identifier": "https://w3id.org/skg-if/sandbox/acme/grant-1", "entity_type": "grant", "titles": { "en": "The EU grant ZZ", diff --git a/openapi/ver/current/skg-if-openapi.yaml b/openapi/ver/current/skg-if-openapi.yaml index acfe2fa..a127986 100644 --- a/openapi/ver/current/skg-if-openapi.yaml +++ b/openapi/ver/current/skg-if-openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: - version: 1.0.0-alpha - title: SKG-IF OpenAPI + version: 1.0.0 + title: SKG-IF OpenAPI - compatible with SKG-IF Data Model 1.1.0 termsOfService: 'https://skg-if.github.io/interoperability-framework/' contact: url: 'https://github.com/skg-if' @@ -16,11 +16,11 @@ info: Last version of the SKG-IF OpenAPI is available at : https://skg-if.github.io/api/ # Note for implementers : - - Please refer to [SKG-IF OpenAPI Implementer documentation](https://docs.google.com/document/d/1t7b7h28UTtM56Sda4NGJIp0hnQfGbcVVGn12fny9wfI/edit?usp=sharing) + - Please refer to the [SKG-IF OpenAPI Implementer documentation](https://docs.google.com/document/d/1t7b7h28UTtM56Sda4NGJIp0hnQfGbcVVGn12fny9wfI/edit?usp=sharing) - [RDA SKG-IF WG](https://skg-if.github.io/) does not provide any official implementation of the current specification. - Recommended OpenAPI viewer : - StopLight/Elements Viewer [Current/last SKG-IF OpenAPI version](https://elements-demo.stoplight.io/?spec=https://w3id.org/skg-if/api/skg-if-openapi.yaml). - - Swagger : [Current/last SKG-IF OpenAPI version](https://editor-next.swagger.io/) + - Swagger : [Current/last SKG-IF OpenAPI version](https://editor.swagger.io/?url=https://w3id.org/skg-if/api/skg-if-openapi.yaml) externalDocs: description: SKG-IF @@ -64,7 +64,7 @@ servers: default: skg-if/api description: service provider skg-if api path paths: - '/products/{short_local_identifier}': + '/products/{local_identifier}': get: tags: - Product @@ -73,7 +73,7 @@ paths: Get single `product`. See definition in SKG-IF [Research product](https://skg-if.github.io/interoperability-framework/docs/research-product.html) ( entity_type:product ). operationId: getProductById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: | @@ -95,7 +95,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -109,11 +112,40 @@ paths: "@context": [ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", - {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + {"@base" : "https://w3id.org/skg-if/sandbox/acme/"} ] + "meta" : + local_identifier: product-1-fgp + entity_type: single_entity + api_items: + - local_identifier: product-1-fgp + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/products/product-1-fgp" + - local_identifier: person-5-mw + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/persons/person-5-mw" + - local_identifier: affiliation-organisation-1 + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/organisations/affiliation-organisation-1" + - local_identifier: datasource-1-aa + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/datasources/datasource-1-aa" + - local_identifier: venue-5-sd + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/venues/venue-5-sd" "@graph" : - - local_identifier: http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869333 - entity_type: product + - local_identifier: "product-1-fgp" + entity_type: "product" product_type: literature titles : "en": ["The FAIR Guiding Principles for scientific data management and stewardship"] @@ -137,11 +169,11 @@ paths: identifiers: - value: "0000-0001-6960-357X" scheme: "orcid" - local_identifier: http://example.com/skg-if/api/persons/otf___1730027051396___person-1 + local_identifier: person-5-mw entity_type: "person" declared_affiliations: - name: "Center for Plant Biotechnology and Genomics, Universidad Politécnica de Madrid, Madrid, 28223, Spain" - local_identifier: http://example.com/skg-if/api/otf___1730027051396___person-1-aff-1 + local_identifier: affiliation-organisation-1 entity_type: "organisation" country: "ES" manifestations: @@ -152,7 +184,7 @@ paths: class: http://www.example.com/types/onto/localtypemethodology biblio: hosting_data_source: - local_identifier: http://example.com/skg-if/api/arch-6f368a3a-b1cf-498f-b2de-27135d1e0075 + local_identifier: datasource-1-aa entity_type: datasource name: "An Archive" in: @@ -161,7 +193,7 @@ paths: identifiers: - "value": "2052-4463" "scheme": "issn" - local_identifier: http://example.com/skg-if/api/venues/journal-46bc1-00f8-42dd-8221-ac4deb52fb25 + local_identifier: venue-5-sd entity_type: "venue" dates: # http://api.crossref.org/works/10.1038/sdata.2016.18 publication: @@ -173,7 +205,8 @@ paths: - "2023-01-04" related_products: cites: - - "614a6575-5d6c-416c-a8e1-f49a5d589bf8" + - local_identifier: product-10 + entity_type: "product" DatasetEx02: summary: "Dataset - OpenAIRE Graph dataset new collected projects" @@ -181,10 +214,19 @@ paths: "@context": [ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", - {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + {"@base" : "https://w3id.org/skg-if/sandbox/acme/"} ] + "meta" : + local_identifier: product-2-ogd + entity_type: single_entity + api_items: + - local_identifier: product-2-ogd + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/products/product-2-ogd" "@graph" : - - local_identifier: http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869555 + - local_identifier: product-2-ogd entity_type: product product_type: research data titles : @@ -232,7 +274,8 @@ paths: | funding. identifiers.scheme | `funding. identifiers.scheme:doi` | __Convenience filters__ \ - These filters aren't attributes of the `product` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `product` object, but they're handy for solving some common use cases. + | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | | cf.search.title | a string | `product` with title containing the filter value | `cf.search.title:ocean` | @@ -299,14 +342,16 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/Product' + oneOf: + - $ref: '#/components/schemas/Product' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] examples: JournalArticleListEx01: @@ -315,7 +360,7 @@ paths: "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" meta: local_identifier: https://example.com/skg-if/api/products?filter=product_type:literature&page=1 entity_type: search_result_page @@ -326,11 +371,22 @@ paths: local_identifier: https://example.com/skg-if/api/products?filter=product_type:literature entity_type: search_result total_items: 54231 + api_items: + - local_identifier: product-500 + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/products/product-500" + - local_identifier: product-501 + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/products/product-501" "@graph": - - local_identifier: http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: product-500 entity_type: product product_type: literature - - local_identifier: http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869999 + - local_identifier: product-501 entity_type: product product_type: research data DatasetListEx02: @@ -339,7 +395,7 @@ paths: "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" meta: local_identifier: http://example.com/skg-if/api/products?filter=product_type:research%20data&page=1 entity_type: search_result_page @@ -350,11 +406,22 @@ paths: local_identifier: http://example.com/skg-if/api/products?filter=product_type:research%20data entity_type: search_result total_items: 13202 + api_items: + - local_identifier: product-500 + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/products/product-1000-ds" + - local_identifier: product-501 + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/products/product-1001-ds" "@graph": - - local_identifier: http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869888 + - local_identifier: product-1000-ds entity_type: product product_type: research data - - local_identifier: http://example.com/skg-if/api/products/prd-c66c6-38be-4d5f-85db-d44c9f869881 + - local_identifier: product-1001-ds entity_type: product product_type: research data '422': @@ -372,7 +439,7 @@ paths: status: '422' detail: 'The filter b is not supported by this implementation, valid filters are x, y, z' occurence: 'http://my-api/products?filter=b:foo,x:bar' - '/persons/{short_local_identifier}': + '/persons/{local_identifier}': get: tags: - Person @@ -381,7 +448,7 @@ paths: Get `person` by id. See definition in SKG-IF [Agent](https://skg-if.github.io/interoperability-framework/docs/agent.html) ( entity_type:person ) .\ operationId: getPersonById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: Success @@ -401,7 +468,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -418,7 +488,7 @@ paths: {"@base" : "http://example.com/"} ] "@graph" : - - local_identifier: http://example.com/skg-if/api/persons/pers-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: person-1-jc entity_type: "person" identifiers: - scheme: orcid @@ -435,9 +505,10 @@ paths: {"@base" : "http://example.com/"} ] "@graph" : - - local_identifier: http://example.com/skg-if/api/persons/otf_126848135_prod-1-pers-1 + - local_identifier: person-2-jd entity_type: "person" name: "John Doe" + '404': description: | Error if entity does not exists @@ -465,7 +536,7 @@ paths: | affiliations.role | `affiliations.role:affiliate` | __Convenience filters__ \ - These filters aren't attributes of the `person` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `person` object, but they're handy for solving some common use cases. | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | @@ -512,14 +583,16 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/Person' + oneOf: + - $ref: '#/components/schemas/Person' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] examples: PersonEx01: @@ -528,7 +601,7 @@ paths: "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" meta: local_identifier: https://example.com/skg-if/api/persons?filter=family_name:Carberry&page=1 entity_type: search_result_page @@ -539,8 +612,19 @@ paths: local_identifier: https://example.com/skg-if/api/persons?filter=family_name:Carberry entity_type: search_result total_items: 4 + api_items: + - local_identifier: person-1-jc + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/persons/person-1-jc" + - local_identifier: person-2-gc + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/persons/person-2-gc" "@graph": - - local_identifier: http://example.com/skg-if/api/persons/pers-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: person-1-jc entity_type: "person" identifiers: - scheme: orcid @@ -548,7 +632,7 @@ paths: given_name: "Josiah" family_name: "Carberry" name: "Josiah Carberry" - - local_identifier: http://example.com/skg-if/api/persons/pers-c66c6-38be-4d5f-85db-d44c9f869888 + - local_identifier: person-2-gc entity_type: "person" given_name: "Gerard" family_name: "Carberry" @@ -561,7 +645,7 @@ paths: operationId: getPersonById parameters: local_identifier: $response.body#/@graph/local_identifier - '/organisations/{short_local_identifier}': + '/organisations/{local_identifier}': get: tags: - Organisation @@ -570,7 +654,7 @@ paths: Get `organisation` by id. See definition in SKG-IF [Agent](https://skg-if.github.io/interoperability-framework/docs/agent.html) ( entity_type:organisation) .\ operationId: getOrganisationById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: Success @@ -591,7 +675,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -605,9 +692,9 @@ paths: "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" "@graph": - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12324_org_1124 + - local_identifier: organisation-2-bu entity_type: 'organisation' identifiers: - scheme: ror @@ -623,9 +710,9 @@ paths: "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" "@graph": - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12325_org_1125 + - local_identifier: organisation-3-jcbl entity_type: 'organisation' identifiers: - scheme: ror @@ -637,15 +724,15 @@ paths: country: US types: - archive - OrgLabScienceNoId: + OrgLabScienceNoRor: summary: "Lab of science" value : "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" "@graph": - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12325_org_1126 + - local_identifier: organisation-5-lsa entity_type: 'organisation' name: Lab of science, unknown University, Antarctica OrgEuropeanCommission: @@ -654,9 +741,9 @@ paths: "@context": - "https://w3id.org/skg-if/context/1.1.0/skg-if.json" - "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json" - - "@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/" + - "@base" : "https://w3id.org/skg-if/sandbox/acme/" "@graph": - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12324_org_1127 + - local_identifier: organisation-6-eu entity_type: 'organisation' identifiers: - scheme: ror @@ -689,7 +776,7 @@ paths: | country | `country:US` | __Convenience filters__ \ - These filters aren't attributes of the `organization` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `organization` object, but they're handy for solving some common use cases. | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | @@ -735,16 +822,18 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/Organisation' + oneOf: + - $ref: '#/components/schemas/Organisation' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] - '/grants/{short_local_identifier}': + '/grants/{local_identifier}': get: tags: - Grant @@ -753,7 +842,7 @@ paths: Get single `grant`. See definition in SKG-IF [Grant](https://skg-if.github.io/interoperability-framework/docs/grant.html) ( entity_type:grant ). operationId: getGrantById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: Success @@ -774,7 +863,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -788,10 +880,34 @@ paths: "@context": [ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", - {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + {"@base" : "https://w3id.org/skg-if/sandbox/acme/"} ] + "meta" : + local_identifier: grant-1-go + entity_type: "single_entity" + api_items: + - local_identifier: grant-1-go + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/grants/grant-1-go" + - local_identifier: person-1-jc + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/persons/person-1-jc" + - local_identifier: person-2-gc + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/persons/person-2-gc" + - local_identifier: organisation-2-bu + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/organisations/organisation-2-bu" "@graph" : - - local_identifier: http://example.com/skg-if/api/grants/grant-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: grant-1-go entity_type: "grant" identifiers: - scheme: "doi" @@ -804,7 +920,7 @@ paths: } acronym: "GraspOS" funding_agency: - local_identifier: http://example.com/skg-if/api/grants/otf___1730027051396___org-1 + local_identifier: organisation-2-bu entity_type: "organisation" identifiers: - scheme: "ror" @@ -821,7 +937,7 @@ paths: end: "2025-12-31T23:59:59Z" website: "https://graspos.eu" beneficiaries: - - local_identifier: http://example.com/skg-if/api/organisations/otf___1730027051396___org-2 + - local_identifier: organisation-2-bu entity_type: "organisation" identifiers: - scheme: "ror" @@ -832,7 +948,7 @@ paths: website: "https://www.brown.edu/" contributions: - by: - local_identifier: http://example.com/skg-if/api/persons/otf___1730027051396___pers-1 + local_identifier: person-1-jc entity_type: "person" identifiers: - scheme: "orcid" @@ -841,7 +957,7 @@ paths: family_name: "Carberry" name: "Josiah Carberro" declared_affiliations: - - local_identifier": "otf___1730027051396___org-2" + - local_identifier": "organisation-2-bu" entity_type": "organisation" identifiers: - scheme: "ror" @@ -908,7 +1024,7 @@ paths: __Convenience filters__ \ - These filters aren't attributes of the `grant` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `grant` object, but they're handy for solving some common use cases. | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | @@ -958,16 +1074,18 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/Grant' + oneOf: + - $ref: '#/components/schemas/Grant' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] - '/venues/{short_local_identifier}': + '/venues/{local_identifier}': get: tags: - Venue @@ -976,7 +1094,7 @@ paths: Get single `venue`. See definition in SKG-IF [Venue](https://skg-if.github.io/interoperability-framework/docs/venue.html) ( entity_type:venue ). operationId: getVenueById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: Success @@ -997,7 +1115,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -1011,10 +1132,19 @@ paths: "@context": [ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", - {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + {"@base" : "https://w3id.org/skg-if/sandbox/acme/"} ] + "meta" : + local_identifier: venue-1-jp + entity_type: "single_entity" + api_items: + - local_identifier: venue-1-jp + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/venues/venue-1-jp" "@graph" : - - local_identifier: http://example.com/skg-if/api/venues/venue-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: venue-1-jp entity_type: "venue" identifiers: - scheme: issn @@ -1046,7 +1176,7 @@ paths: | name | `name:Journal of Psychoceramics` | __Convenience filters__ \ - These filters aren't attributes of the `venue` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `venue` object, but they're handy for solving some common use cases. | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | @@ -1084,16 +1214,18 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/Venue' + oneOf: + - $ref: '#/components/schemas/Venue' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] - '/topics/{short_local_identifier}': + '/topics/{local_identifier}': get: tags: - Topic @@ -1102,7 +1234,7 @@ paths: Get single `topic`. See definition in SKG-IF [Topic](https://skg-if.github.io/interoperability-framework/docs/topic.html) ( entity_type:topic ). operationId: getTopicById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: Success @@ -1123,7 +1255,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -1137,10 +1272,19 @@ paths: "@context": [ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", - {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + {"@base" : "https://w3id.org/skg-if/sandbox/acme/"} ] + "meta" : + local_identifier: topic-1-cs + entity_type: "single_entity" + api_items: + - local_identifier: topic-1-cs + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/topics/topc-1-cs" "@graph" : - - local_identifier: http://example.com/skg-if/api/topics/topic-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: topic-1-cs entity_type: "topic" identifiers: - scheme: wikidata @@ -1169,7 +1313,7 @@ paths: | identifiers.value | `identifiers.value:https://www.wikidata.org/wiki/Q42` | __Convenience filters__ \ - These filters aren't attributes of the `topic` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `topic` object, but they're handy for solving some common use cases. | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | @@ -1221,16 +1365,18 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/Topic' + oneOf: + - $ref: '#/components/schemas/Topic' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] - '/datasources/{short_local_identifier}': + '/datasources/{local_identifier}': get: tags: - Data Source @@ -1239,7 +1385,7 @@ paths: Get single `datasource`. See definition in SKG-IF [Data Source](https://skg-if.github.io/interoperability-framework/docs/data-source.html) ( entity_type:datasource ). operationId: getDataSourceById parameters: - - $ref : '#/components/parameters/shortLocalIdPathParam' + - $ref : '#/components/parameters/localIdPathParam' responses: '200': description: Success @@ -1260,7 +1406,10 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] + meta: + type: object + $ref: '#/components/schemas/MetaSingleEntity' "@graph": type: array minItems: 1 @@ -1274,10 +1423,19 @@ paths: "@context": [ "https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", - {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"} + {"@base" : "https://w3id.org/skg-if/sandbox/acme/"} ] + "meta" : + local_identifier: datasource-1-oura + entity_type: "single_entity" + api_items: + - local_identifier: datasource-1-oura + urls: + - entity_type: "link" + rel: "self" + href: "https://example.com/skg-if/api/venues/datasource-1-oura" "@graph" : - - local_identifier: http://example.com/skg-if/api/datasources/datasrc-c66c6-38be-4d5f-85db-d44c9f869333 + - local_identifier: datasource-1-oura entity_type: "datasource" identifiers: - scheme: doi @@ -1311,7 +1469,7 @@ paths: | acronym | `acronym:CIKM` | __Convenience filters__ \ - These filters aren't attributes of the `datasource` object, but they're handy for solving some common use cases. + These filters (`cf.*`) aren't attributes of the `datasource` object, but they're handy for solving some common use cases. | Filter key | Filter value | List returned | Attribute filter example | | -------- | -------- | ------- | ------- | @@ -1349,14 +1507,16 @@ paths: - $ref: '#/components/schemas/JsonLdCtxSearch' - $ref: '#/components/schemas/JsonLdCtxBaseOrMore' examples: - - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/my-skg-acronym/"}] + - ["https://w3id.org/skg-if/context/1.1.0/skg-if.json", "https://w3id.org/skg-if/context/1.0.0/skg-if-api.json", {"@base" : "https://w3id.org/skg-if/sandbox/acme/"}] meta: type: object - $ref: '#/components/schemas/Meta' + $ref: '#/components/schemas/MetaSearch' "@graph": type: array items: - $ref: '#/components/schemas/DataSource' + oneOf: + - $ref: '#/components/schemas/DataSource' + - $ref: '#/components/schemas/LocalIdentifierRef' required: [ "@context", "meta", "@graph" ] components: securitySchemes: @@ -1376,13 +1536,12 @@ components: type: http scheme: basic parameters: - shortLocalIdPathParam: - name: short_local_identifier + localIdPathParam: + name: local_identifier in: path description: | - entity id. URL suffix used in OpenAPI get by id operations. \ - `https://[your-server-root-skg-if-url]/[products|persons|organisations|datasources|venues|topics]/{short_local_identifier}` \ - example `http://example.com/skg-if/api/products/c66c6-38be-4d5f-85db-d44c9` + entity id. URL. \ + example `http://skgbase.example.com/prod-c66c6-38be-4d5f-85db-d44c9` required: true schema: type: string @@ -1410,6 +1569,101 @@ components: schema: type: integer schemas: + LocalIdentifierRef: + type: string + description: | + A local identifier reference. + + You can pass a local identifier as a string and not a full object entity structure, but it is not recommended. + ex: + ``` + "foo":"product-1" + ``` + + This feature is included in the current SKG-IF OpenAPI specifications to remain compatible with SKG-IF model documentation and raw exports. + This approach creates important limitations for the client applications explained below. + + Instead, we recommend to pass one of the object structure entities compatible with this property, and also fill its properties. + One additional benefit of object structure is to limit the client API calls to resolve entities and sub-entities. + ex: + ``` + "foo": { + "local_identifier":"product-1", + "entity_type:product", + "title":"xxx", + ... + "contributions" : [ + { + "by": { + "local_identifier":"person-1", + "entity_type:person", + "name":"John Doe", + ... + } + } + ] + } + ``` + + This is also very useful for client using your API for autocomplete features. + A typical autocomplete use case is : search products by term and get a list of products with the contributors names in a single API call. + ApiItem: + type: object + title: 'Link' + description: | + Result element + required: [ + "local_identifier" + ] + properties: + local_identifier: + type: string + description: | + Unique local identifier as URL + examples: + - http://w3id.org/skg-if/sandbox/acme/product-1 + - http://w3id.org/skg-if/sandbox/acme/person-1 + urls: + type: array + description: | + List of API URLs to access to the entity metadata + items: + $ref: '#/components/schemas/Link' + Link: + type: object + title: 'Link' + description: | + Link to resource (API, web...\ + The main expected link on entities, is a `self` relation with `href` link pointing to the SKG-IF API endpoint for this entity.\ + ex: `https://example.com/skg-if/api/products/product-1`. + Note: as a client you should not expect to have an HTTP 200 response on a `self` API link on entities with an `otf` `local_identifier` + properties: + entity_type: + default: "link" + type: string + x-faker: + helpers.arrayElement: [["link"]] + rel: + default: "self" + description: | + Link relation. + Use `self` value for SKG-IF API only. + You can also use values defined in [IANA](https://www.iana.org/assignments/link-relations/link-relations.xhtml). + You can use `describedBy`, combined with the `media_type` property, to link to other API and representation of the entity. + type: string + x-faker: + helpers.arrayElement: [["self"]] + href: + type: string + description: "a URL. For `rel:self`should be SKG-IF endpoint" + x-faker: + fake : ['https://example.com/skg-if/api/products/product-{{random.alphaNumeric(8)}}'] + media_type: + default: "link" + type: string + description: "Media type. Leave empty for `rel:self`" + x-faker: + helpers.arrayElement: [["text/xml"]] Product: type: object title: 'Product' @@ -1480,7 +1734,9 @@ components: required: [ "term" ] properties: term: - $ref: '#/components/schemas/Topic' + oneOf: + - $ref: '#/components/schemas/Topic' + - $ref: '#/components/schemas/LocalIdentifierRef' # TODO provenance ? contributions: type: array @@ -1496,17 +1752,20 @@ components: type: array description: List of relevant Organisation associated with the `product`, in case the individual affiliations of a `person` are not available. items: - $ref: '#/components/schemas/Organisation' + oneOf: + - $ref: '#/components/schemas/Organisation' + - $ref: '#/components/schemas/LocalIdentifierRef' funding: type: array description: List of `grant` associated with the `product` items: - $ref: '#/components/schemas/GrantLite' + oneOf: + - $ref: '#/components/schemas/GrantLite' + - $ref: '#/components/schemas/LocalIdentifierRef' related_products: - $ref: '#/components/schemas/ProductRelated' - + $ref: '#/components/schemas/ProductsRelated' examples: - - local_identifier: http://example.com/skg-if/api/products/xxx + - local_identifier: product-1-fgp entity_type: product product_type: literature titles : @@ -1530,11 +1789,11 @@ components: identifiers: - value: "0000-0001-6960-357X" scheme: "orcid" - local_identifier: http://example.com/skg-if/api/persons/614a6575-5d6c-416c-a8e1-f49a5d589bf8 + local_identifier: person-5-mw entity_type: "person" declared_affiliations: - name: "Center for Plant Biotechnology and Genomics, Universidad Politécnica de Madrid, Madrid, 28223, Spain" - local_identifier: http://example.com/skg-if/api/persons/32bc66c6-38be-4d5f-85db-d44c9f86921f + local_identifier: affiliation-organisation-1 entity_type: "organisation" country: "ES" manifestations: @@ -1545,7 +1804,7 @@ components: class: http://www.example.com/types/onto/localtypemethodology biblio: hosting_data_source: - local_identifier: http://example.com/skg-if/api/datasources/6f368a3a-b1cf-498f-b2de-27135d1e0075 + local_identifier: datasource-1-aa entity_type: datasource name: "An Archive" in: @@ -1554,7 +1813,7 @@ components: identifiers: - "value": "2052-4463" "scheme": "issn" - local_identifier: http://example.com/skg-if/api/datasources/51f46bc1-00f8-42dd-8221-ac4deb52fb25 + local_identifier: venue-5-sd entity_type: "venue" dates: # http://api.crossref.org/works/10.1038/sdata.2016.18 publication: @@ -1565,7 +1824,7 @@ components: deposit: - "2023-01-04" funding: - - local_identifier: http://example.com/skg-if/api/grants/614a6575-5d6c-416c-a8e1-f49a5d58999 + - local_identifier: grant-7-zz entity_type: "grant" titles: - en: "EU grant ZZ" @@ -1586,6 +1845,7 @@ components: - $ref: '#/components/schemas/PersonLite' - $ref: '#/components/schemas/Organisation' - $ref: '#/components/schemas/Agent' + - $ref: '#/components/schemas/LocalIdentifierRef' discriminator: propertyName: entity_type mapping: @@ -1596,7 +1856,9 @@ components: description: List of `organisation` that reflect the declared affiliations of a `person` contributing to a `product`. type: array items: - $ref: '#/components/schemas/Organisation' + oneOf: + - $ref: '#/components/schemas/Organisation' + - $ref: '#/components/schemas/LocalIdentifierRef' rank: type: integer x-faker: @@ -1819,43 +2081,62 @@ components: x-faker: fake : ['{{datatype.number(5)}}'] in: - $ref: '#/components/schemas/VenueLite' + oneOf: + - $ref: '#/components/schemas/VenueLite' + - $ref: '#/components/schemas/LocalIdentifierRef' hosting_data_source : - $ref: '#/components/schemas/DataSourceLite' - ProductRelated: + oneOf: + - $ref: '#/components/schemas/DataSourceLite' + - $ref: '#/components/schemas/LocalIdentifierRef' + ProductsRelatedItem: + type: object + description: "Reference to a `product` object" + allOf: + - $ref: "#/components/schemas/Entity" + - type: object + required: [ + "local_identifier","entity_type" + ] + properties: + entity_type: + default: "product" + type: string + x-faker: + helpers.arrayElement: [["product"]] + ProductsRelated: type: object description : A dictionary of objects representing related `product`, where the semantics of such relationships is specified as a key. properties : cites: type: array items: - local_identifier: - type: string - description: "`product` local_identifier" + oneOf : + - $ref: '#/components/schemas/ProductsRelatedItem' + - $ref: '#/components/schemas/LocalIdentifierRef' is_supplemented_by: type: array items: - local_identifier: - type: string - description: "`product` local_identifier" + oneOf : + - $ref: '#/components/schemas/ProductsRelatedItem' + - $ref: '#/components/schemas/LocalIdentifierRef' is_documented_by: type: array items: - local_identifier: - type: string - description: "`product` local_identifier" + oneOf: + - $ref: '#/components/schemas/ProductsRelatedItem' + - $ref: '#/components/schemas/LocalIdentifierRef' is_new_version_of: type: array items: - local_identifier: - type: string - description: "`product` local_identifier" + oneOf : + - $ref: '#/components/schemas/ProductsRelatedItem' + - $ref: '#/components/schemas/LocalIdentifierRef' is_part_of: type: array items: - local_identifier: - type: string - description: "`product` local_identifier" + oneOf : + - $ref: '#/components/schemas/ProductsRelatedItem' + - $ref: '#/components/schemas/LocalIdentifierRef' Agent: type: object title: "Agent" @@ -1982,7 +2263,7 @@ components: - research - unspecified examples: - - local_identifier: 'otf_session12324_org_1124' + - local_identifier: 'organisation-2-bu' entity_type: 'organisation' identifiers: - "scheme": ror @@ -1992,7 +2273,7 @@ components: country: US types: - education - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12325_org_1125 + - local_identifier: organisation-3-jcbl entity_type: 'organisation' identifiers: - scheme: ror @@ -2004,10 +2285,10 @@ components: country: US types: - archive - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12325_org_1126 + - local_identifier: organisation-5-lsa entity_type: 'organisation' name: Lab of science, unknown University, Antarctica - - local_identifier: http://example.com/skg-if/api/organisations/otf_session12324_org_1127 + - local_identifier: organisation-6-eu entity_type: 'organisation' identifiers: - scheme: ror @@ -2052,7 +2333,7 @@ components: type: string description: end date. Format [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) compliant string ( "2024-10-01", "2024-10", "2024" ).' examples: - - local_identifier: http://example.com/skg-if/api/persons/otf_session12324_person_1124 + - local_identifier: person-1-jc entity_type: 'person' identifiers: - scheme: orcid @@ -2066,7 +2347,7 @@ components: start: "2010-08-24" end: "2020-08-24" affiliation: - local_identifier: http://example.com/skg-if/api/organisatios/otf_session12324_org_1124 + local_identifier: organisation-2-bu entity_type: 'organisation' identifiers: - scheme: ror @@ -2127,7 +2408,7 @@ components: examples : - Josiah Carberro examples: - - local_identifier: http://example.com/skg-if/api/persons/otf_session12324_person_1124 + - local_identifier: person-1-jc entity_type: 'person' identifiers: - scheme: orcid @@ -2234,12 +2515,16 @@ components: description: "List of `organisation` funded by the `grant`" type: array items: - $ref: '#/components/schemas/Organisation' + oneOf: + - $ref: '#/components/schemas/Organisation' + - $ref: '#/components/schemas/LocalIdentifierRef' contributions: type: array description: List of objects describing a `person` or `organisation`, its role, contribution, rank, when working on the `grant`. items: - $ref: '#/components/schemas/GrantContribution' + oneOf: + - $ref: '#/components/schemas/GrantContribution' + - $ref: '#/components/schemas/LocalIdentifierRef' GrantContribution: type: object title: 'GrantContribution' @@ -2250,6 +2535,7 @@ components: oneOf: - $ref: '#/components/schemas/PersonLite' - $ref: '#/components/schemas/Organisation' + - $ref: '#/components/schemas/LocalIdentifierRef' discriminator: propertyName: entity_type mapping: @@ -2259,7 +2545,9 @@ components: description: List of `organisation` that reflect the declared affiliations of a `person` contributing to a `grant`. type: array items: - $ref: '#/components/schemas/Organisation' + oneOf: + - $ref: '#/components/schemas/Organisation' + - $ref: '#/components/schemas/LocalIdentifierRef' roles: description: | The roles that a `person` or `organisation` had in a `grant`.\ @@ -2506,22 +2794,29 @@ components: local_identifier: type: string description: | - Unique local identifier as URL. \ - `https://[your-server-root-skg-if-url]/[products|persons|organisations|datasources|venues|topics]/{short_local_identifier}` \ - example `http://example.com/skg-if/api/products/c66c6-38be-4d5f-85db-d44c9` \ - \ - If the entity does not have any stable identifier an on-the-fly identifier is returned : `otf______`. + Unique local identifier as URL. + format : `https://[your-@base-url]/{identifier string}` + example: `https://w3id.org/skg-if/sandbox/acme/prod-1` + + The local identifier value can contain only the `{identifier string}` part only if the `@base` is present in the `@context` output. \ + The local identifier value can also be an URL reference not included in your `@base` domain. + This can be useful for entities identified in your system by their external PID only (RoR, DOI...) + + If the entity does not have any stable identifier, an on-the-fly identifier is returned : `otf______`. - `otf` stands for on-the-fly to explicitly clarify the local identifiers it has been created for the purpose of creating this SKG-IF document; - `` is a string portion that enables the source to uniquely identifier the session in which such SKG-IF document has been created - e.g. it could be the current time of the software run to create the SKG expressed in milliseconds; - `` is a string portion that identifies the particular entity in consideration. - For instance, a possible example of such a local identifier would be : `otf___1730027051396___person-1`. An on-the-fly may not resolve with URL `//`. + For instance, a possible example of such a local identifier would be : `otf___1730027051396___person-1`. + + An on-the-fly may not resolve with its `self` API link URL ex: `https://example.com/skg-if/api/persons/otf___1730027051396___person-1`. + on-the-fly means that this local identifier cannot be resolved outside the session context. x-faker: fake : ['{{random.uuid}}'] examples: - - http://example.com/skg-if/api/products/c66c6-38be-4d5f-85db-d44c9 - - http://example.com/skg-if/api/products/otf___1730027051396___prod-1 - - http://example.com/skg-if/api/persons/c7777-38be-4d5f-85db-d7777 - - http://example.com/skg-if/api/persons/otf___1730027051396___person-1 + - http://w3id.org/skg-if/sandbox/acme/product-1 + - http://w3id.org/skg-if/sandbox/acme/person-1 + - http://w3id.org/skg-if/sandbox/acme/otf___1730027051396___person-1 + - http://w3id.org/skg-if/sandbox/acme/otf___1730027051396___product-1 identifiers: type: array items: @@ -2535,13 +2830,32 @@ components: type: string entity_type: type: string - Meta: + MetaSingleEntity: + type: object + required: [ "local_identifier", "entity_type" ] + properties: + local_identifier: + type: string + description: entity id as URL + examples: + - http://w3id.org/skg-if/sandbox/acme/product-1 + - http://w3id.org/skg-if/sandbox/acme/person-1 + entity_type: + type: string + description: single entity + enum: + - single_entity + api_items: + type: array + items: + $ref: '#/components/schemas/ApiItem' + MetaSearch: type: object required: [ "local_identifier", "entity_type" ] properties: local_identifier: type: string - description: search result page id + description: search result page id as SKG-IF API URL examples: - https://example.com/skg-if/api/products?filter=xxx&page=y - https://example.com/skg-if/api/persons?filter=xxx&page=y @@ -2565,7 +2879,7 @@ components: properties: local_identifier: type: string - description: search result id as URL + description: search result id as SKG-IF API URL examples: - https://example.com/skg-if/api/products?filter=xxx - https://example.com/skg-if/api/persons?filter=xxx @@ -2587,12 +2901,16 @@ components: description: Last page reference of the search type: object $ref: '#/components/schemas/SearchResultPage' + api_items: + type: array + items: + $ref: '#/components/schemas/ApiItem' SearchResultPage: type: object properties: local_identifier: type: string - description: search result page id as URL + description: search result page id as SKG-IF API URL examples: - https://example.com/skg-if/api/products?filter=xxx&page=y - https://example.com/skg-if/api/persons?filter=xxx&page=y @@ -2645,22 +2963,27 @@ components: x-faker: fake: ['https://w3id.org/skg-if/context/1.0.0/skg-if-api.json'] JsonLdCtxBaseOrMore: - description : 'Additional context mappings ex: `{ "@base":"https://w3id.org/skg-if/sandbox/my-skg-acronym" }`' + description : 'Additional context mappings ex: `{ "@base":"https://w3id.org/skg-if/sandbox/acme" }`' properties: "@base": type: string description : | - Default base URL specific to the implementer.\ - common format : `https://w3id.org/skg-if/sandbox/{my-skg-acronym}` \ - example : `https://w3id.org/skg-if/sandbox/openaire/` + Default root URL of the JSON-LD context. \ + To define your `@base`, please refer to the [SKG-IF OpenAPI Implementer documentation](https://docs.google.com/document/d/1t7b7h28UTtM56Sda4NGJIp0hnQfGbcVVGn12fny9wfI/edit?usp=sharing) \ + Your `@base` should end with a `/` \ + common formats : \ + - `https://acme.com/skg/` \ + - `https://w3id.org/acme/` \ + - `https://w3id.org/skg-if/sandbox/acme/`\ x-faker: fake: ['https://w3id.org/skg-if/sandbox/{{random.alpha(5)}}/'] examples: - - "https://w3id.org/skg-if/sandbox/openaire/" - - "https://w3id.org/skg-if/sandbox/cessda/" - - "https://w3id.org/skg-if/sandbox/foobar/" + - "https://acme.com/skg/" + - "https://acme.com/graph/" + - "https://w3id.org/acme/" + - "https://w3id.org/skg-if/sandbox/acme/" additionalProperties: type: string description: "context URL of extension entities" x-faker: - fake : ['http://www.example.com/skg-if/{{random.alpha(3)}}'] + fake : ['http://www.example.com/skg/{{random.alpha(3)}}']