{# -*- 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 %}
⬅️ {{ _("To parent page") }}

{{ _("API Documentation") }}

{{ _("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 %}

{{ _("Authentication") }}

{%- 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 %}

{{ _("Common Query Parameters") }}

{{ _("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 %}

{{ _("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.") }}

{{ _("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:") }} GET /api/records/{record_id}

{{ _("Token Required:") }} {{ _("No") }}

cURL:

{#- ################# PREFORMATTED AREA TEXT BEGIN ################# #}
curl "{{ config.SITE_API_URL }}/records/abcde-12345"
{#- ################## PREFORMATTED AREA TEXT END ################## -#}
        
      

Python (requests):

{#- ################# 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 ################## -#}
        
      

{{ _("Example Response") }} (HTTP 200 - OK):

{#- ################# 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.).") }}

{{ _("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:") }} GET /api/records

{{ _("Token Required:") }} {{ _("No") }}

{{ _("Query Parameters:") }} q, sort, and page

cURL:

{#- ################# 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 ################## -#}
        
      

Python (requests):

{#- ################# 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 ################## -#}
        
      

{{ _("Example Response") }} (HTTP 200 - OK):

{#- ################# 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 ################## -#}
        
      

💡 {%- 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.

{%- endtrans %}

{{ _("Case 3 - Upload a New Dataset: Automate metadata submissions and record creation.") }}

{{ _("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.") }}

{{ _("Workflow:") }}
  1. {{ _("Create a new draft:") }}

    {{ _("Endpoint:") }} POST /api/records

    {{ _("Token Required:") }} {%- trans trimmed token_link = token_link %} Yes — generate one here. {%- endtrans %}


  2. {{ _("Request a DOI:") }}


    {{ _("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 ################## -#}
        
      

{{ _("Case 4 - Attach a File to an Existing Record: Enrich records by associating files using a multi-step upload process.") }}

{{ _("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.") }}

{{ _("Workflow:") }}
  1. {{ _("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 %}


  2. {{ _("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 %}


  3. {{ _("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 %}


  4. {%- 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 ################## -#}
        
      

{{ _("Case 5 - File Download: Retrieving Contents from a Record.") }}

{{ _("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 ################## -#}
        
      

{{ _("Additional Customizations") }}

{{ _("Extended Functionality: Custom Endpoints") }}

{{ _("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:") }}

  • {{ _("Curation Workflow Requests:") }}

    {{ _("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 ################## -#}
                
              
  • Invenio-DAMAP {{ _("Endpoints") }}:

    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 %}

{{ _("Additional Resources") }}

{%- 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 %}