Developers | Zenodo Developers About Blog Help Developers NAV Python cURL NodeJS Privacy policy Cookie policy Terms of Use Contact REST API Introduction The Zenodo REST API currently supports: Deposit — upload and publishing of research outputs (identical to functionality avail…
Developers | Zenodo Developers About Blog Help Developers NAV Python cURL NodeJS Privacy policy Cookie policy Terms of Use Contact REST API Introduction The Zenodo REST API currently supports: Deposit — upload and publishing of research outputs (identical to functionality available in the user interface). Records — search published records. Files — download/upload of files. Check out the Quickstart guide for an example on how to programmatically upload and publish your research outputs. The following REST APIs are currently in testing before we launch them in beta with full documentation: Communities - search communities. Funders — search for funders. Grants — search for grants. Licenses — search for licenses. You can have a sneak peek at the APIs in test from our root endpoint: https://zenodo.org/api/ Quickstart - Upload This short guide will give a quick overview of how to upload and publish on Zenodo, and will be using either: Python together with the Requests package. Javascript together with the axios package. # Install 'requests' module for python pip install requests # Install 'axios' module for nodejs npm install axios First, make sure you have the Requests module installed for python or axios for nodeJS: python # Python 3.6.5 # [GCC 4.8.1] on linux2 # Type "help", "copyright", "credits" or "license" for more information. node // Welcome to Node.js v14.19.0. // Type ".help" for more information. Next, fire up a command prompt: import requests const axios = require('axios'); Import the module to handle requests: import requests r = requests.get("https://zenodo.org/api/deposit/depositions") r.status_code # 401 r.json() const axios = require('axios'); axios.get("https://zenodo.org/api/deposit/depositions").then(response => { console.log(response); }).catch(error => { console.log(error.response.data); }); { "message": "The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.", "status": 401 } We will try to access the API without an authentication token: All API access requires an access token, so create one. ACCESS_TOKEN = 'ChangeMe' headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'} r = requests.get('https://zenodo.org/api/deposit/depositions', headers=headers) r.status_code # 200 r.json() # [] const ACCESS_TOKEN = 'ChangeMe' const requestConfig = { headers: { 'Authorization': `Bearer ${ACCESS_TOKEN}` } } axios.get("https://zenodo.org/api/deposit/depositions", requestConfig).then(response => { console.log(response.status); // > 200 console.log(response.data); // > [] }).catch(error => { console.log(error.response.data); }); Let’s try again (replace ACCESS_TOKEN with your newly created personal access token): Note, if you already uploaded something, the output will be different. headers = { "Content-Type": "application/json", "Authorization": f"Bearer {ACCESS_TOKEN}" } r = requests.post('https://sandbox.zenodo.org/api/deposit/depositions', json={}, headers=headers) r.status_code # 201 r.json() const requestConfig = { headers: { "Content-Type": "application/json", "Authorization": `Bearer ${ACCESS_TOKEN}` } } axios.post("https://zenodo.org/api/deposit/depositions", {}, requestConfig).then(response => { console.log(response.status); // 201 console.log(response.data); }).catch(error => { console.log(error.response.data); }); { "conceptrecid": "542200", "created": "2020-05-19T11:58:41.606998+00:00", "files": [], "id": 542201, "links": { "bucket": "https://zenodo.org/api/files/568377dd-daf8-4235-85e1-a56011ad454b", "discard": "https://zenodo.org/api/deposit/depositions/542201/actions/discard", "edit": "https://zenodo.org/api/deposit/depositions/542201/actions/edit", "files": "https://zenodo.org/api/deposit/depositions/542201/files", "html": "https://zenodo.org/deposit/542201", "latest_draft": "https://zenodo.org/api/deposit/depositions/542201", "latest_draft_html": "https://zenodo.org/deposit/542201", "publish": "https://zenodo.org/api/deposit/depositions/542201/actions/publish", "self": "https://zenodo.org/api/deposit/depositions/542201" }, "metadata": { "prereserve_doi": { "doi": "10.5072/zenodo.542201", "recid": 542201 } }, "modified": "2020-05-19T11:58:41.607012+00:00", "owner": 12345, "record_id": 542201, "state": "unsubmitted", "submitted": false, "title": "" } Next, let’s create a new empty upload: Now, let’s upload a new file. We have recently released a new API, which is significantly more perfomant and supports much larger file sizes. While the older API supports 100MB per file, the new one has a limit of 50GB total in the record (and any given file), and up to 100 files in the record. bucket_url = r.json()["links"]["bucket"] curl -H "Authorization: Bearer $ACCESS_TOKEN" \ https://zenodo.org/api/deposit/depositions/222761 { ... "links": { "bucket": "https://zenodo.org/api/files/568377dd-daf8-4235-85e1-a56011ad454b", ..., }, ... } To use the new files API we will do a PUT request to the bucket link. The bucket is a folder-like object storing the files of our record. Our bucket URL will look like this: https://zenodo.org/api/files/568377dd-daf8-4235-85e1-a56011ad454b and can be found under the links key in our records metadata. ''' This will stream the file located in '/path/to/your/file.dat' and store it in our bucket. The uploaded file will be named according to the last argument in the upload URL, 'file.dat' in our case. ''' $ curl --upload-file /path/to/your/file.dat \ -H "Authorization: Bearer $ACCESS_TOKEN" \ https://zenodo.org/api/files/568377dd-daf8-4235-85e1-a56011ad454b/file.dat { ... } ''' New API ''' filename = "my-file.zip" path = "/path/to/%s" % filename headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'} ''' The target URL is a combination of the bucket link with the desired filename seperated by a slash. ''' with open(path, "rb") as fp: r = requests.put( "%s/%s" % (bucket_url, filename), data=fp, headers=headers, ) r.json() const fs = require('fs'); const axios = require('axios'); const filePath = '<FILE_PATH>'; // Replace with file path const bucketURL = '<BUCKET_URL>'; // Replace with bucket url const fileName = '<FILE_NAME>'; // Replace with file name const token = 'TOKEN'; // Replace with token value // Create a form const form = new FormData(); // Read file as a stream const stream = fs.createReadStream(filePath); form.append('file', stream); // Create request let url = `${bucketURL}/${fileName}`; let headers = { 'Content-type': 'application/zip', 'Authorization': `Bearer ${token}` } const requestConfig = { data: { name: fileName, ...form }, headers: headers } axios.put(url, requestConfig).then(response => { console.log(response.data); }).catch(error => { console.log(error.response.data); }); { "key": "my-file.zip", "mimetype": "application/zip", "checksum": "md5:2942bfabb3d05332b66eb128e0842cff", "version_id": "38a724d3-40f1-4b27-b236-ed2e43200f85", "size": 13264, "created": "2020-02-26T14:20:53.805734+00:00", "updated": "2020-02-26T14:20:53.811817+00:00", "links": { "self": "https://zenodo.org/api/files/44cc40bc-50fd-4107-b347-00838c79f4c1/dummy_example.pdf", "version": "https://zenodo.org/api/files/44cc40bc-50fd-4107-b347-00838c79f4c1/dummy_example.pdf?versionId=38a724d3-40f1-4b27-b236-ed2e43200f85", "uploads": "https://zenodo.org/api/files/44cc40bc-50fd-4107-b347-00838c79f4c1/dummy_example.pdf?uploads" }, "is_head": true, "delete_marker": false } ''' Old API Get the deposition id from the previous response ''' deposition_id = r.json()['id'] data = {'name': 'myfirstfile.csv'} files = {'file': open('/path/to/myfirstfile.csv', 'rb')} headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'} r = requests.post('https://zenodo.org/api/deposit/depositions/%s/files' % deposition_id, headers=headers, data=data, files=files) r.status_code # 201 r.json() // Old API documentation not available for javascript / NodeJS { "checksum": "2b70e04bb31f2656ce967dc07103297f", "name": "myfirstfile.csv", "id": "eb78d50b-ecd4-407a-9520-dfc7a9d1ab2c", "filesize": "27" } Here are the instructions for the old files API: data = { 'metadata': { 'title': 'My first upload', 'upload_type': 'poster', 'description': 'This is my first upload', 'creators': [{'name': 'Doe, John', 'affiliation': 'Zenodo'}] } } headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {ACCESS_TOKEN}' } r = requests.put('https://zenodo.org/api/deposit/depositions/%s' % deposition_id, data=json.dumps(data), headers=headers) r.status_code # 200 // Old API documentation not available for javascript / NodeJS Last thing missing, is just to add some metadata: headers = {'Authorization': f'Bearer {ACCESS_TOKEN}'} r = requests.post('https://zenodo.org/api/deposit/depositions/%s/actions/publish' % deposition_id, headers=headers) r.status_code # 202 // Old API documentation not available for javascript / NodeJS And we’re ready to publish: Don’t execute this last step - it will put your test upload straight online. Testing We provide a sandbox environment where you can test your API integration during development. The sandbox environment is available at https://sandbox.zenodo.org. Please note the following: The sandbox environment can be cleaned at anytime. The sandbox environment requires a separate registration and separate access token from the ones used on https://zenodo.org. The sandbox environment will issue test DOIs using the 10.5072 prefix instead of Zenodo’s normal prefix (10.5281). Versioning The REST API is versioned. We strive not to make backward incompatible changes to the API, but if we do, we release a new version. Changes to the API are documented on this page, and advance notification is given on our Twitter account. Authentication All API requests must be authenticated and over HTTPS. Any request over plain HTTP will fail. We support authentication with via OAuth 2.0. Creating a personal access token Register for a Zenodo account if you don’t already have one. Go to your Applications, to create a new token. Select the OAuth scopes you need (for the quick start tutorial you need deposit:write and deposit:actions). Do not share your personal access token with anyone else, and only use it over HTTPS. Using access tokens An access token must be included in all requests. The recommended and more secure method is using HTTP headers: GET /api/deposit/depositions Authorization: Bearer <ACCESS_TOKEN> Recommended: as HTTP request header (Authorization): GET /api/deposit/depositions?access_token=<ACCESS_TOKEN> or as URL parameter (named access_token), though this is less secure: Scopes Scopes assigns permissions to your access token to limit access to data and actions in Zenodo. The following scopes exist: Name Description deposit:write Grants write access to depositions, but does not allow publishing the upload. deposit:actions Grants access to publish, edit and discard edits for depositions. Requests The base URL of the API is https://zenodo.org/api/. All POST and PUT request bodies must be JSON encoded, and must have content type of application/json unless specified otherwise in the specific resource (e.g. in the case of file uploads). The API will return a 415 error (see HTTP status codes and error responses) if the wrong content type is provided. Responses { "field1": "value", "...": "..." } All response bodies are JSON encoded (UTF-8 encoded). A single resource is represented as a JSON object: [ { "field1": "value", "...": "..." } "..." ] A collection of resources is represented as a JSON array of objects: YYYY-MM-DDTHH:MM:SS+00:00 Timestamps are in UTC and formatted according to ISO 8601: HTTP status codes We use the following HTTP status codes to indicate success or failure of a request. Code Name Description 200 OK Request succeeded. Response included. Usually sent for GET/PUT/PATCH requests. 201 Created Request succeeded. Response included. Usually sent fo…