{# -*- coding: utf-8 -*-
Copyright (C) 2025 TU Wien.
Invenio Theme TUW is free software; you can redistribute it and/or modify it
under the terms of the MIT License; see LICENSE file for more details.
#}
{%- extends config.BASE_TEMPLATE %}
{# These links are used multiple times throughout this page. #}
{% set inveniordm_api_ref_link = "https://inveniordm.docs.cern.ch/reference/rest_api_index/" %}
{% set token_link = url_for("invenio_oauth2server_settings.token_new") %}
{# NOTE: Set API cases text here (sequentially) #}
{%
set api_cases_text = [
"Retrieve a Dataset's Metadata",
"Search for Datasets",
"Upload a New Dataset",
"Attach a File to an Existing Record",
"File Download",
]
%}
{%- block page_hero %}
{%- endblock page_hero %}
{%- block page_body %}
{{ _("The %(sitename)s API provides programmatic access to datasets, metadata, search functionalities, and more.", sitename=config.THEME_SITENAME) }}
{{ _("This API lets you automate data management tasks, integrate with external systems, or build custom workflows for data analysis and visualization.") }}
{{ _("In this page we list the most common API operations which include:") }}
{{ _("While our customized implementation inherits all the core functionalities from a vanilla InvenioRDM instance, it introduces several enhancements to better serve the research community:") }}
{%- trans trimmed tuw_customizations_link = "#tuw_customizations" %}
For detailed examples of our enhanced Curation Workflow and Invenio-DAMAP integration, please see the Additional Customizations section below.
{%- endtrans %}
{%- trans trimmed token_link = token_link %}
Note: Operations such as creating records or attaching files require an access token. You can generate one
here.
Other operations (like retrieving metadata) are public.
{%- endtrans %}
{{ _("For search endpoints, the most relevant parameters include:") }}
{%- trans trimmed inveniordm_api_ref_link = inveniordm_api_ref_link %}
More details about query parameters can be found in the official InvenioRDM API Documentation.
{%- endtrans %}
{{ _("User Story:") }}
{{ _("As a researcher, I want to quickly retrieve detailed metadata for a dataset using its unique identifier so that I can verify its relevance and incorporate accurate information into my analysis.") }}
{{ _("Endpoint:") }} {{ _("Token Required:") }} {{ _("No") }} cURL: Python (requests): {{ _("Example Response") }} (HTTP 200 - OK):
{{ _("User Story:") }}
{{ _("As a data scientist, I want to search for datasets using keywords and publication ranges, or author names so that I can find data that matches my research criteria without browsing through irrelevant records.") }}
{{ _("Endpoint:") }} {{ _("Token Required:") }} {{ _("No") }} {{ _("Query Parameters:") }} cURL: Python (requests): {{ _("Example Response") }} (HTTP 200 - OK):
💡
{%- trans trimmed search_link = url_for("invenio_app_rdm.help_search") %}
Hint: You can refer to our search guide for further details on how to construct simple or advanced search queries.{{ _("API Documentation") }}
{% for case in api_cases_text %}
{% set index = loop.index %}
{{ _("Authentication") }}
{{ _("Common Query Parameters") }}
q
: {{ _("The search query") }} ({{ _("e.g.") }}, q=title:climate
).sort
: {{ _("Sorting criteria") }} ({{ _("e.g.") }}, sort=newest
).size
: {{ _("Results size per page") }} ({{ _("e.g.") }}, size=50
).page
: {{ _("Pagination control") }} ({{ _("e.g.") }}, page=1
).{{ _("API Usage Examples") }}
{# TODO: This could be reworked with a loop, use the 'api_cases_text' list defined above? #}
{# If possible, then readjust translation strings: should be marked only with the 2nd sentence here due to trans property above. #}
{{ _("Case 1 - Retrieve a Dataset's Metadata: Quickly fetch detailed metadata for a dataset using its persistent identifier.") }}
GET /api/records/{record_id}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
curl "{{ config.SITE_API_URL }}/records/abcde-12345"
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
import requests
url = "{{ config.SITE_API_URL }}/records/abcde-12345"
response = requests.get(url)
print(response.json())
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
{
"id": "abcde-12345",
"metadata": {
"title": "Dataset Title",
"creators": [{"name": "Doe, John"}],
"publication_date": "2025-01-09",
"resource_type": {"id": "dataset", "title": {"en": "Dataset"}}
},
"links": {
"self": "{{ config.SITE_API_URL }}/records/abcde-12345",
"files": "{{ config.SITE_API_URL }}/records/abcde-12345/files"
}
}
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Case 2 - Search for Datasets: Execute advanced searches with filters (keywords, authors, dates, etc.).") }}
GET /api/records
q
, sort
, and page
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
curl -G "{{ config.SITE_API_URL }}/records" \
--data-urlencode "q=climate AND metadata.publication_date:[2023 TO 2025]" \
--data-urlencode "sort=newest" \
--data-urlencode "page=1"
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
import requests
params = {
"q": "climate AND metadata.publication_date=[2023 TO 2025]",
"sort": "newest",
"page": 1
}
url = "{{ config.SITE_API_URL }}/records"
response = requests.get(url, params=params)
print(response.json())
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
{
"hits": {
"total": 2,
"hits": [
{
"id": "abcde-12345",
"metadata": {
"title": "Climate Change Data",
"publication_date": "2025-01-01"
}
},
{
"id": "efgh-5678",
"metadata": {
"title": "Temperature Records",
"publication_date": "2024-12-25"
}
}
]
},
"links": {
"self": "{{ config.SITE_API_URL }}/records?q=climate&sort=newest&page=1",
"next": "{{ config.SITE_API_URL }}/records?q=climate&sort=newest&page=2"
}
}
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("User Story:") }} {{ _("As a lab scientist, I want to automate the upload of new datasets along with detailed metadata so that my research outputs are quickly published, discoverable, and citable through an assigned DOI.") }}
{{ _("Create a new draft:") }}
{{ _("Endpoint:") }} POST /api/records
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
{{ _("Endpoint:") }} POST /api/records/{record_id}/draft/pids/doi
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
cURL {{ _("Snippets") }}:
{{ _("Step 1: Create a new draft") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X POST "{{ config.SITE_API_URL }}/records" \ -H "Authorization: Bearer {your-access-token}" \ -H "Content-Type: application/json" \ -d ' { "metadata": { "creators": [ { "person_or_org": { "family_name": "Doe", "given_name": "Jane", "type": "personal" } } ], "publication_date": "2025-01-09", "publisher": "TU Wien", "resource_type": {"id": "dataset"}, "title": "New Dataset Title" }, "files": {"enabled": true} }' {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Step 2: Request a DOI") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/pids/doi" \ -H "Authorization: Bearer {your-access-token}" {#- ################## PREFORMATTED AREA TEXT END ################## -#}
Python (requests) {{ _("Snippets") }}:
{{ _("Step 1: Create a new draft") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/records" headers = { "Authorization": "Bearer {your-access-token}", "Content-Type": "application/json" } data = { "metadata": { "creators": [ { "person_or_org": { "family_name": "Doe", "given_name": "Jane", "type": "personal", } } ], "publication_date": "2025-01-09", "publisher": "TU Wien", "resource_type": {"id": "dataset"}, "title": "New Dataset Title", }, "files": {"enabled": True}, } response = requests.post(url, json=data, headers=headers) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Step 2: Request a DOI") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/pids/doi" headers = { "Authorization": "Bearer {your-access-token}", } response = requests.post(url, headers=headers) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("User Story:") }} {{ _("As a project manager, I want to attach supplementary files (like additional data or documentation) to an existing dataset record so that all components of the research project are organized and accessible in one place.") }}
{{ _("Initialize the file upload:") }}
{{ _("Endpoint:") }}: POST /api/records/{record_id}/draft/files
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
{{ _("Upload the file content:") }}
{{ _("Endpoint:") }} PUT /api/records/{record_id}/draft/files/{file_name}/content
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
{{ _("Commit draft file upload:") }}
{{ _("Endpoint:") }} POST /api/records/{record_id}/draft/files/{file_name}/commit
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
{%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} Publish the draft: (After curation request has been accepted - See curation endpoint)
{%- endtrans %}{{ _("Endpoint:") }} POST /api/records/{record_id}/draft/actions/publish
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
cURL {{ _("Snippets") }}:
{{ _("Step 1: Initialize File Upload") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files" \ -H "Authorization: Bearer {your-access-token}" \ -H "Content-Type: application/json" \ -d ' { "files": [{"key": "example_dataset.csv"}] }' {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Step 2: Upload File Content") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X PUT "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/content" \ -H "Authorization: Bearer {your-access-token}" \ -H "Content-Type: application/octet-stream" \ --data-binary @example_dataset.csv {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Step 3: Commit Draft File Upload") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/commit" \ -H "Authorization: Bearer {your-access-token}" {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} Step 4: Publish the Draft (After curation request has been accepted - See curation endpoint) {%- endtrans %}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X POST "{{ config.SITE_API_URL }}/records/abcde-12345/draft/actions/publish" \ -H "Authorization: Bearer {your-access-token}" {#- ################## PREFORMATTED AREA TEXT END ################## -#}
Python (requests) {{ _("Snippets") }}:
{{ _("Step 1: Initialize File Upload") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files" headers = { "Authorization": "Bearer {your-access-token}", "Content-Type": "application/json" } data = [ { "key": "example_dataset.csv" } ] response = requests.post(url, json=data, headers=headers) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Step 2: Upload File Content") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/content" headers = { "Authorization": "Bearer {your-access-token}", "Content-Type": "application/octet-stream" } with open("example_dataset.csv", "rb") as file_data: response = requests.put(url, headers=headers, data=file_data) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Step 3: Commit Draft File Upload") }}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/files/example_dataset.csv/commit" headers = { "Authorization": "Bearer {your-access-token}", } response = requests.post(url, headers=headers) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{%- trans trimmed tuw_customizations_link = "#tuw_customizations" %} Step 4: Publish the Draft (After curation request has been accepted - See curation endpoint) {%- endtrans %}
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/records/abcde-12345/draft/actions/publish" headers = { "Authorization": "Bearer {your-access-token}", } data = { "metadata": { "title": "New Dataset Title", "creators": [{"name": "Doe, Jane"}], "publication_date": "2025-01-09", "resource_type": {"id": "dataset"} }, "files": {"enabled": True} } response = requests.post(url, json=data, headers=headers) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("User Story:") }} {{ _("As a researcher, I want to download an individual file from a dataset so that I can analyze its contents locally without navigating through multiple interfaces.") }}
{{ _("Endpoint:") }} GET /api/records/{record_id}/files/{filename}/content
{{ _("Token Required:") }} {{ _("No") }}
cURL:
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -JO "{{ config.SITE_API_URL }}/records/abcde-12345/files/example_dataset.csv/content" {#- ################## PREFORMATTED AREA TEXT END ################## -#}
Python (requests):
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import os, re, requests url = "{{ config.SITE_API_URL }}/records/abcde-12345/files/example_dataset.csv/content" response = requests.get(url, stream=True) content_disposition = response.headers.get("Content-Disposition", "") filename = re.search(r'filename="([^"]+)"', content_disposition).group(1) with open(filename, "wb") as f: for chunk in response.iter_content(chunk_size=8192): _ = f.write(chunk) print("File saved at: ", os.path.abspath(filename)) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Example Response Headers") }} (HTTP 200 - OK):
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} Content-Disposition: attachment; filename="example_dataset.csv" Content-Length: 5577907 Content-Type: application/octet-stream Date: Mon, 28 Fri 2025 13:56:29 GMT ETag: "674c65f3-551cb3" Last-Modified: Sun, 01 Dec 2024 13:34:43 GMT {#- ################## PREFORMATTED AREA TEXT END ################## -#}
{{ _("Our customized instance of the repository comes with additional endpoints that differ from what would be expected from a standard Invenio RDM installation.") }} {{ _("These improvements cover the following:") }}
{{ _("We offer an API that supports a custom curation process. Custom endpoints assign curators to records, review submissions, add curation notes, and allow publishing of curated content.") }} {{ _("This workflow guarantees that data quality and compliance standards are met prior to data being made public.") }}
{{ _("Create a new curation request:") }}
{{ _("Endpoint:") }} POST /api/curations/
{{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}
cURL:
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} curl -X POST "{{ config.SITE_API_URL }}/curations/" \ -H "Authorization: Bearer {your-access-token}" \ -H "Content-Type: application/json" \ -d ' { "topic":{ "record": "fghij-54321" } }' {#- ################## PREFORMATTED AREA TEXT END ################## -#}
Python (requests):
{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #} import requests url = "{{ config.SITE_API_URL }}/curations/" headers = { "Authorization": "Bearer {your-access-token}", } data = { "topic":{ "record": "fghij-54321" } } response = requests.post(url, json=data, headers=headers) print(response.json()) {#- ################## PREFORMATTED AREA TEXT END ################## -#}
Additionally, we provide extra endpoints that ship with the Invenio-DAMAP package. {{ _("They allow to directly link your record to a DAMAP-based system, by automatically filling specific DMP fields, saving you time and effort.") }} {%- trans trimmed damap_page_link = url_for("invenio_theme_tuw.tuw_about_damap") %} For further details about this integration, visit the dedicated DAMAP page. {%- endtrans %}
{%- trans trimmed inveniordm_api_ref_link = inveniordm_api_ref_link %} For further details, please refer to the official InvenioRDM API Documentation. {%- endtrans %}
{%- block javascript %} {{ super() }} {{ webpack["invenio-theme-tuw-clipboard.js"] }} {%- endblock javascript %} {%- endblock page_body %}