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 Python together with the Requests package.
$ pip install requests
- First, make sure you have the
Requests module
installed:
$ python
Python 3.6.5
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
- Next, fire up a Python command prompt:
import requests
- Import the
requestsmodule:
>>> import requests
>>> r = requests.get("https://zenodo.org/api/deposit/depositions")
>>> r.status_code
401
>>> r.json()
{
"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'
>>> r = requests.get('https://zenodo.org/api/deposit/depositions',
... params={'access_token': ACCESS_TOKEN})
>>> r.status_code
200
>>> r.json()
[]
- Let’s try again (replace
ACCESS_TOKENwith your newly created personal access token):
>>> headers = {"Content-Type": "application/json"}
>>> params = {'access_token': ACCESS_TOKEN}
>>> r = requests.post('https://sandbox.zenodo.org/api/deposit/depositions',
params=params,
json={},
# Headers are not necessary here since "requests" automatically
# adds "Content-Type: application/json", because we're using
# the "json=" keyword argument
# headers=headers,
headers=headers)
>>> r.status_code
201
>>> r.json()
{
"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 no size limitation.
bucket_url = r.json()["links"]["bucket"]
curl https://zenodo.org/api/deposit/depositions/222761?access_token=$ACCESS_TOKEN
{ ...
"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 https://zenodo.org/api/files/568377dd-daf8-4235-85e1-a56011ad454b/file.dat?access_token=$ACCES_TOKEN
{ ... }
# NEW API
filename = "my-file.zip"
path = "/path/to/%s" % filename
# We pass the file object (fp) directly to the request as the 'data' to be uploaded.
# The target URL is a combination of the buckets 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,
# No headers included in the request, since it's a raw byte request
params=params,
)
r.json()
{
"mimetype": "application/pdf",
"updated": "2020-02-26T14:20:53.811817+00:00",
"links": {"self": "https://sandbox.zenodo.org/api/files/44cc40bc-50fd-4107-b347-00838c79f4c1/dummy_example.pdf",
"version": "https://sandbox.zenodo.org/api/files/44cc40bc-50fd-4107-b347-00838c79f4c1/dummy_example.pdf?versionId=38a724d3-40f1-4b27-b236-ed2e43200f85",
"uploads": "https://sandbox.zenodo.org/api/files/44cc40bc-50fd-4107-b347-00838c79f4c1/dummy_example.pdf?uploads"},
"is_head": true,
"created": "2020-02-26T14:20:53.805734+00:00",
"checksum": "md5:2942bfabb3d05332b66eb128e0842cff",
"version_id": "38a724d3-40f1-4b27-b236-ed2e43200f85",
"delete_marker": false,
"key": "dummy_example.pdf",
"size": 13264
}
# 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')}
>>> r = requests.post('https://zenodo.org/api/deposit/depositions/%s/files' % deposition_id,
... params={'access_token': ACCESS_TOKEN}, data=data,
... files=files)
>>> r.status_code
201
>>> r.json()
{
"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'}]
... }
... }
>>> r = requests.put('https://zenodo.org/api/deposit/depositions/%s' % deposition_id,
... params={'access_token': ACCESS_TOKEN}, data=json.dumps(data),
... headers=headers)
>>> r.status_code
200
- Last thing missing, is just to add some metadata:
>>> r = requests.post('https://zenodo.org/api/deposit/depositions/%s/actions/publish' % deposition_id,
params={'access_token': ACCESS_TOKEN} )
>>> r.status_code
202
- And we’re ready to publish:
Testing
We provide a sandbox environment where you can test your API integration during development. The sandbox environment is available at http://sandbox.zenodo.org.
Please note that the sandbox environment can be cleaned at anytime. Also, 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:writeanddeposit:actions).
Using access tokens
An access token must be included in all requests as either:
GET /api/deposit/depositions?access_token=<ACCESS_TOKEN>
- an URL parameter (named
access_token):
GET /api/deposit/depositions
Authorization: Bearer <ACCESS_TOKEN>
- or as HTTP request header (
Authorization):
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 for POST requests. |
202 |
Accepted | Request succeeded. Response included. Usually sent for POST requests, where background processing is needed to fulfill the request. |
204 |
No Content | Request succeeded. No response included. Usually sent for DELETE requests. |
400 |
Bad Request | Request failed. Error response included. |
401 |
Unauthorized | Request failed, due to an invalid access token. Error response included. |
403 |
Forbidden | Request failed, due to missing authorization (e.g. deleting an already submitted upload or missing scopes for your access token). Error response included. |
404 |
Not Found | Request failed, due to the resource not being found. Error response included. |
405 |
Method Not Allowed | Request failed, due to unsupported HTTP method. Error response included. |
409 |
Conflict | Request failed, due to the current state of the resource (e.g. edit a deopsition which is not fully integrated). Error response included. |
415 |
Unsupported Media Type | Request failed, due to missing or invalid request header Content-Type. Error response included. |
429 |
Too Many Requests | Request failed, due to rate limiting. Error response included. |
500 |
Internal Server Error | Request failed, due to an internal server error. Error response NOT included. Don’t worry, Zenodo admins have been notified and will be dealing with the problem ASAP. |
Errors
Error responses for 400 series errors (e.g. 400, 401, 403, …) are returned as
a JSON object with two attributes message and status (HTTP status code), and
possibly an attribute errors with a list of more detailed errors.
{
"message": "Deposition not found",
"status": 404
}
Example of a simple error message without further detailed errors:
{
"message": "Validation error",
"status": 400,
"errors": [
{"code": 10, "message":"Not a valid choice", "field": "access_right"}
]
}
Example of an error message with additional detailed error messages:
The attribute errors is a JSON array of objects, with the attributes message
and code, and possibly field for validation errors.
Entities
Depositions
Representation
The Deposition resource is used for uploading and editing records on Zenodo.
Deposit
| Field | Description |
|---|---|
createdtimestamp |
Creation time of deposition (in ISO8601 format). |
doistring |
Digital Object Identifier (DOI). When you publish your deposition, we register a DOI in DataCite for your upload, unless you manually provided us with one. This field is only present for published depositions. |
doi_urlurl |
Persistent link to your published deposition. This field is only present for published depositions. |
filesarray |
A list of deposition files resources. |
idinteger |
Deposition identifier |
metadataobject |
A deposition metadata resource |
modifiedtimestamp |
Last modification time of deposition (in ISO8601 format). |
ownerinteger |
User identifier of the owner of the deposition. |
record_idinteger |
Record identifier. This field is only present for published depositions. |
record_urlurl |
URL to public version of record for this deposition. This field is only present for published depositions. |
statestring |
One of the values: * inprogress: Deposition metadata can be updated. If deposition is also unsubmitted (see submitted) files can be updated as well. * done: Deposition has been published. * error: Deposition is in an error state - contact our support. |
submittedbool |
True of deposition has been published, False otherwise. |
titlestring |
Title of deposition (automatically set from metadata). Defaults to empty string. |
Deposit metadata
| Attribute | Required | Description |
|---|---|---|
upload_typestring |
Yes | Controlled vocabulary: * publication: Publication* poster: Poster* presentation: Presentation* dataset: Dataset* image: Image* video: Video/Audio* software: Software* lesson: Lesson* other: Other |
publication_typestring |
Yes, if upload_type is "publication". |
Controlled vocabulary: * annotationcollection: Annotation collection* book: Book* section: Book section* conferencepaper: Conference paper* datamanagementplan: Data management plan* article: Journal article* patent: Patent* preprint: Preprint* deliverable: Project deliverable* milestone: Project milestone* proposal: Proposal* report: Report* softwaredocumentation: Software documentation* taxonomictreatment: Taxonomic treatment* technicalnote: Technical note* thesis: Thesis* workingpaper: Working paper* other: Other |
image_typestring |
Yes, if upload_type is "image". |
Controlled vocabulary: * figure: Figure* plot: Plot* drawing: Drawing* diagram: Diagram* photo: Photo* other: Other |
publication_datestring |
Yes | Date of publication in ISO8601 format (YYYY-MM-DD). Defaults to current date. |
titlestring |
Yes | Title of deposition. |
creatorsarray of objects |
Yes | The creators/authors of the deposition. Each array element is an object with the attributes: * name: Name of creator in the format Family name, Given names* affiliation: Affiliation of creator (optional).* orcid: ORCID identifier of creator (optional).* gnd: GND identifier of creator (optional).Example: [{'name':'Doe, John', 'affiliation': 'Zenodo'}, {'name':'Smith, Jane', 'affiliation': 'Zenodo', 'orcid': '0000-0002-1694-233X'}, {'name': 'Kowalski, Jack', 'affiliation': 'Zenodo', 'gnd': '170118215'}] |
descriptionstring (allows HTML) |
Yes | Abstract or description for deposition. |
access_rightstring |
Yes | Controlled vocabulary: * open: Open Access* embargoed: Embargoed Access* restricted: Restricted Access* closed: Closed Access Defaults to open. |
licensestring |
Yes, if access_right is "open" or "embargoed". |
Controlled vocabulary: The selected license applies to all files in this deposition, but not to the metadata which is licensed under Creative Commons Zero. Further information about licenses is available at Open Definition Licenses Service. Defaults to cc-by for non-datasets and cc-zero for datasets. |
embargo_datedate |
Yes, if access_right is "embargoed". |
When the deposited files will be made automatically made publicly available by the system. Defaults to current date. |
access_conditionsstring (allows HTML) |
Yes, if access_right is "restricted". |
Specify the conditions under which you grant users access to the files in your upload. User requesting access will be asked to justify how they fulfil the conditions. Based on the justification, you decide who to grant/deny access. You are not allowed to charge users for granting access to data hosted on Zenodo. |
doistring |
No | Digital Object Identifier. Did a publisher already assign a DOI to your deposited files? If not, leave the field empty and we will register a new DOI for you when you publish. A DOI allow others to easily and unambiguously cite your deposition. |
prereserve_doiobject/bool |
No | Set to true, to reserve a Digital Object Identifier (DOI). The DOI is automatically generated by our system and cannot be changed. Also, The DOI is not registered with DataCite until you publish your deposition, and thus cannot be used before then. Reserving a DOI is useful, if you need to include it in the files you upload, or if you need to provide a dataset DOI to your publisher but not yet publish your dataset. The response from the REST API will include the reserved DOI. |
keywordsarray of strings |
No | Free form keywords for this deposition. Example: ["Keyword 1", "Keyword 2"] |
notesstring (allows HTML) |
No | Additional notes. |
related_identifiersarray of objects |
No | Persistent identifiers of related publications and datasets. Supported identifiers include: DOI, Handle, ARK, PURL, ISSN, ISBN, PubMed ID, PubMed Central ID, ADS Bibliographic Code, arXiv, Life Science Identifiers (LSID), EAN-13, ISTC, URNs and URLs. Each array element is an object with the attributes: * identifier: The persistent identifier* relation: Relationship. Controlled vocabulary (isCitedBy, cites, isSupplementTo, isSupplementedBy, isNewVersionOf, isPreviousVersionOf, isPartOf, hasPart, compiles, isCompiledBy, isIdenticalTo, isAlternateIdentifier).Example: [{'relation': 'isSupplementTo', 'identifier':'10.1234/foo'}, {'relation': 'cites', 'identifier':'https://doi.org/10.1234/bar'} ] Note the identifier type (e.g. DOI) is automatically detected, and used to validate and normalize the identifier into a standard form. |
contributorsarray of objects |
No | The contributors of the deposition (e.g. editors, data curators, etc.). Each array element is an object with the attributes: * name: Name of creator in the format Family name, Given names* type: Contributor type. Controlled vocabulary (ContactPerson, DataCollector, DataCurator, DataManager,Distributor, Editor, Funder, HostingInstitution, Producer, ProjectLeader, ProjectManager, ProjectMember, RegistrationAgency, RegistrationAuthority, RelatedPerson, Researcher, ResearchGroup, RightsHolder,Supervisor, Sponsor, WorkPackageLeader, Other)* affiliation: Affiliation of creator (optional).* orcid: ORCID identifier of creator (optional).* gnd: GND identifier of creator (optional).Example: [{'name':'Doe, John', 'affiliation': 'Zenodo', 'type': 'Editor' }, ...] |
referencesarray of strings |
No | List of references. Example: ["Doe J (2014). Title. Publisher. DOI", "Smith J (2014). Title. Publisher. DOI"] |
communitiesarray of objects |
No | List of communities you wish the deposition to appear. The owner of the community will be notified, and can either accept or reject your request. Each array element is an object with the attributes: * identifier: Community identifierExample: [{'identifier':'ecfunded'}] |
grantsarray of objects |
No | List of OpenAIRE-supported grants, which have funded the research for this deposition. Each array element is an object with the attributes: * id: grant ID.Example: [{'id':'283595'}] (European Commission grants only)or funder DOI-prefixed: [{'id': '10.13039/501100000780::283595'}] (All grants, recommended)Accepted funder DOI prefixes: Australian Research Council: 10.13039/501100000923European Commission: 10.13039/501100000780Fundação para a Ciência e a Tecnologia: 10.13039/501100001871Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja: 10.13039/501100004564Ministarstvo Znanosti, Obrazovanja i Sporta: 10.13039/501100006588National Health and Medical Research Council: 10.13039/501100000925National Science Foundation: 10.13039/100000001Nederlandse Organisatie voor Wetenschappelijk Onderzoek: 10.13039/501100003246Wellcome Trust: 10.13039/100004440 |
journal_titlestring |
No | Journal title, if deposition is a published article. |
journal_volumestring |
No | Journal volume, if deposition is a published article. |
journal_issuestring |
No | Journal issue, if deposition is a published article. |
journal_pagesstring |
No | Journal pages, if deposition is a published article. |
conference_titlestring |
No | Title of conference (e.g. 20th International Conference on Computing in High Energy and Nuclear Physics). |
conference_acronymstring |
No | Acronym of conference (e.g. CHEP'13). |
conference_datesstring |
No | Dates of conference (e.g. 14-18 October 2013). Conference title or acronym must also be specified if this field is specified. |
conference_placestring |
No | Place of conference in the format city, country (e.g. Amsterdam, The Netherlands). Conference title or acronym must also be specified if this field is specified. |
conference_urlstring |
No | URL of conference (e.g. http://www.chep2013.org/). |
conference_sessionstring |
No | Number of session within the conference (e.g. VI). |
conference_session_partstring |
No | Number of part within a session (e.g. 1). |
imprint_publisherstring |
No | Publisher of a book/report/chapter |
imprint_isbnstring |
No | ISBN of a book/report |
imprint_placestring |
No | Place of publication of a book/report/chapter in the format city, country. |
partof_titlestring |
No | Title of book for chapters |
partof_pagesstring |
No | Pages numbers of book |
thesis_supervisorsarray of objects |
No | Supervisors of the thesis. Same format as for creators. |
thesis_universitystring |
No | Awarding university of thesis. |
subjectsarray of objects |
No | Specify subjects from a taxonomy or controlled vocabulary. Each term must be uniquely identified (e.g. a URL). For free form text, use the keywords field. Each array element is an object with the attributes: * term: Term from taxonomy or controlled vocabulary.* identifier: Unique identifier for term.* scheme: Persistent identifier scheme for id (automatically detected).Example: [{"term": "Astronomy", "identifier": "http://id.loc.gov/authorities/subjects/sh85009003", "scheme": "url"}] |
versionstring |
No | Version of the resource. Any string will be accepted, however the suggested format is a semantically versioned tag (see more details on semantic versioning at semver.org) Example: 2.1.5 |
languagestring |
No | Specify the main language of the record as ISO 639-2 or 639-3 code, see Library of Congress ISO 639 codes list. Example: eng |
locationsarray of objects |
No | List of locations * lat (double): latitude * lon (double): longitude* place (string): place’s name (required)* description (string): place’s description (optional)Example: [{"lat": 34.02577, "lon": -118.7804, "place": "Los Angeles"}, {"place": "Mt.Fuji, Japan", "description": "Sample found 100ft from the foot of the mountain."}] |
datesarray of objects |
No | List of date intervals * start (ISO date string): start date (*) * end (ISO date string): end date (*)* type (Collected, Valid, Withdrawn): The interval’s type (required)* description (string): The interval’s description (optional)(*) Note that you have to specify at least a start or end date. For an exact date, use the same value for both start and end.Example: [{"start": "2018-03-21", "end": "2018-03-25", "type": "Collected", "description": "Specimen A5 collection period."}] |
methodstring (allows HTML) |
No | The methodology employed for the study or research. |
List
List all depositions for the currently authenticated user.
import requests
response = requests.get('/api/deposit/depositions',
params={'q': 'my title',
'access_token': ACCESS_TOKEN})
print(response.json())
curl -i /api/deposit/depositions/?access_token=ACCESS_TOKEN
HTTP Request
GET /api/deposit/depositions
Query arguments
| Parameter | Required | Description |
|---|---|---|
qstring |
optional | Search query (using Elasticsearch query string syntax). |
statusstring |
optional | Filter result based on deposit status (either draft or published) |
sortstring |
optional | Sort order (bestmatch or mostrecent). Prefix with minus to change form ascending to descending (e.g. -mostrecent). |
pageinteger |
optional | Page number for pagination. |
sizeinteger |
optional | Number of results to return per page. |
Success Response
- Code:
200 OK - Body: an array of deposition resources.
Error Response
See HTTP status codes (400 and 500 series errors) and error responses.
Create
Create a new deposition resource.
curl -i -H "Content-Type: application/json" -X POST
--data '{}' /api/deposit/depositions/?access_token=ACCESS_TOKEN
# or
curl -i -H "Content-Type: application/json" -X POST
--data '{"metadata": {"title": "My first upload", "upload_type": "poster", "description": "This is my first upload", "creators": [{"name": "Doe, John", "affiliation": "Zenodo"}]}}' /api/deposit/depositions/?access_token=ACCESS_TOKEN
import json
import requests
url = "/api/deposit/depositions/?access_token=ACCESS_TOKEN"
headers = {"Content-Type": "application/json"}
r = requests.post(url, data="{}", headers=headers)
HTTP Request
POST /api/deposit/depositions
Request headers
Content-Type: application/json
Data
An empty JSON object {} or a deposition metadata
resource. Example: {"metadata": {"upload_type": "presentation" } }
Scopes
deposit:write
Success Response
- Code:
201 Created - Body: a deposition resource.
Error Response
See HTTP status codes (400 and 500 series errors) and error responses.
Retrieve
Retrieve a single deposition resource.
curl -i /api/deposit/depositions/1234?access_token=ACCESS_TOKEN
import requests
r = requests.get("/api/deposit/depositions/1234?access_token=ACCESS_TOKEN")
HTTP Request
GET /api/deposit/depositions/:id
Success response
- Code:
200 OK - Body: a deposition resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses. |
Update
Update an existing deposition resource.
curl -i -H "Content-Type: application/json" -X PUT
--data '{"metadata": {"title": "My first upload", "upload_type": "poster", "description": "This is my first upload", "creators": [{"name": "Doe, John", "affiliation": "Zenodo"}]}}' https://zenodo.org/api/deposit/depositions/1234?access_token=ACCESS_TOKEN
import json
import requests
data = {
"metadata": {
"title": "My first upload",
"upload_type": "poster",
"description": "This is my first upload",
"creators": [
{"name": "Doe, John", "affiliation": "Zenodo"}
]
}
}
url = "https://zenodo.org/api/deposit/depositions/1234?access_token=ACCESS_TOKEN"
headers = {"Content-Type": "application/json"}
r = requests.put(url, data=json.dumps(data), headers=headers)
HTTP Request
PUT /api/deposit/depositions/:id
Request headers
Content-Type: application/json
Scopes
deposit:write
{
"metadata": {
"upload_type": "presentation",
"...": "..."
}
}
Data parameters
A deposition metadata resource.
Success response
- Code:
200 OK - Body: a deposition resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Delete
Delete an existing deposition resource. Note, only unpublished depositions may be deleted.
curl -i https://zenodo.org/api/deposit/depositions/1234?access_token=ACCESS_TOKEN -X DELETE
import requests
r = requests.delete('https://zenodo.org/api/deposit/depositions/1234',
params={'access_token': ACCESS_TOKEN})
HTTP Request
DELETE /api/deposit/depositions/:id
Scopes
deposit:write
Success Response
- Code:
201 Created - Body: Empty.
Error Response
404 Not found: Deposition does not exist.403 Forbidden: Deleting an already published deposition.
See also HTTP status codes (400 and 500 series errors) and error responses.
Deposition files
Representation
The Deposition file resource is used for uploading and editing files of a deposition on Zenodo.
Deposition File
| Attribute | Description |
|---|---|
idstring |
Deposition file identifier |
filenamestring |
Name of file |
filesizeinteger |
Size of file in bytes |
checksumstring |
MD5 checksum of file, computed by our system. This allows you to check the integrity of the uploaded file. |
List
List all deposition files for a given deposition.
curl -i https://zenodo.org/api/deposit/depositions/1234/files?access_token=ACCESS_TOKEN
import requests
r = requests.get('https://zenodo.org/api/deposit/depositions/1234/files',
params={'access_token': ACCESS_TOKEN})
HTTP Request
GET /api/deposit/depositions/:id/files
Success response
- Code:
200 OK - Body: an array of deposition file resources.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Create
Upload a new file.
curl -i https://zenodo.org/api/deposit/depositions/1234/files?access_token=ACCESS_TOKEN
-F name=myfirstfile.csv
-F file=@path/to/local_file.csv
import json
import requests
url = 'https://zenodo.org/api/deposit/depositions/1234/files?access_token=ACCESS_TOKEN'
data = {'name': 'myfirstfile.csv'}
files = {'file': open('path/to/local_file.csv', 'rb')}
r = requests.post(url, data=data, files=files)
HTTP Request
POST /api/deposit/depositions/:id/files
Request headers
Content-Type: multipart/form-data
Scopes
deposit:write
Success response
- Code:
201 Created - Body: a deposition file resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Sort
Sort the files for a deposition. By default, the first file is shown in the file preview.
curl -i https://zenodo.org/api/deposit/depositions/1234/files?access_token=ACCESS_TOKEN -X PUT
-H "Content-Type: application/json"
--data '[{"id":"21fedcba-9876-5432-1fed-cba987654321"}, {"id":"12345678-9abc-def1-2345-6789abcdef12"}]'
import json
import requests
url = 'https://zenodo.org/api/deposit/depositions/1234/files?access_token=ACCESS_TOKEN'
headers = {"Content-Type": "application/json"}
data = [{'id': '21fedcba-9876-5432-1fed-cba987654321'},
{'id': '12345678-9abc-def1-2345-6789abcdef12'}]
r = requests.put(url, data=json.dumps(data), headers=headers)
HTTP Request
PUT /api/deposit/depositions/:id/files
Request headers
Content-Type: application/json
Scopes
deposit:write
Data
A JSON array of partial deposition file resources with only
the id attribute. Example:
[
{"id": "<file_id_1>"},
{"id": "<file_id_2>"},
"..."
]
Success response
- Code:
200 OK - Body: an array of deposition file resources.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Retrieve
Retrieve a single deposition file.
curl -i https://zenodo.org/api/deposit/depositions/1234/files/12345678-9abc-def1-2345-6789abcdef12?access_token=ACCESS_TOKEN
import requests
r = requests.get('https://zenodo.org/api/deposit/depositions/1234/files/12345678-9abc-def1-2345-6789abcdef12',
params={'access_token': ACCESS_TOKEN})
HTTP Request
GET /api/deposit/depositions/:id/files/:file_id
Success Response
- Code:
200 OK - Body: a deposition file resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Update
Update a deposition file resource. Currently the only use is renaming an already uploaded file. If you one to replace the actual file, please delete the file and upload a new file.
curl -i https://zenodo.org/api/deposit/depositions/1234/files/21fedcba-9876-5432-1fed-cba987654321?access_token=ACCESS_TOKEN -X PUT
-H "Content-Type: application/json"
--data '{"filename": "someothername.csv"}'
import json
import requests
url = 'https://zenodo.org/api/deposit/depositions/1234/files/21fedcba-9876-5432-1fed-cba987654321?access_token=ACCESS_TOKEN'
headers = {"Content-Type": "application/json"}
data = {"name": "someothername.csv"}
r = requests.put(url, data=json.dumps(data), headers=headers)
HTTP Request
PUT /api/deposit/depositions/:id/files/:file_id
Request headers
Content-Type: application/json
Scopes
deposit:write
Data
A partial deposition file resources with only the
filename attributes. Example:
{
"name": "<new_file_name>"
}
Success response
- Code:
200 OK - Body: a deposition file resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Delete
Delete an existing deposition file resource. Note, only deposition files for unpublished depositions may be deleted.
curl -i -X DELETE https://zenodo.org/api/deposit/depositions/1234/files/21fedcba-9876-5432-1fed-cba987654321?access_token=ACCESS_TOKEN
import requests
r = requests.delete('https://zenodo.org/api/deposit/depositions/1234/files/21fedcba-9876-5432-1fed-cba987654321',
params={'access_token': ACCESS_TOKEN})
HTTP Request
DELETE /api/deposit/depositions/:id/files/:file_id
Scopes
deposit:write
Success response
- Code:
204 No Content - Body: Empty.
Error response
404 Not found: Deposition file does not exist.403 Forbidden: Deleting an already published deposition.
See also HTTP status codes (400 and 500 series errors) and error responses.
Deposition actions
Publish
Publish a deposition. Note, once a deposition is published, you can no longer delete it.
curl -i -X POST https://zenodo.org/api/deposit/depositions/1234/actions/publish?access_token=ACCESS_TOKEN
import requests
r = requests.post('https://zenodo.org/api/deposit/depositions/1234/actions/publish',
params={'access_token': ACCESS_TOKEN})
HTTP Request
POST /api/deposit/depositions/:id/actions/publish
Scopes
deposit:actions
Success response
- Code:
202 Accepted - Body: a deposition resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Edit
Unlock already submitted deposition for editing.
curl -i -X POST https://zenodo.org/api/deposit/depositions/1234/actions/edit?access_token=ACCESS_TOKEN
import requests
r = requests.post('https://zenodo.org/api/deposit/depositions/1234/actions/edit',
params={'access_token': ACCESS_TOKEN})
HTTP Request
POST /api/deposit/depositions/:id/actions/edit
Scopes
deposit:actions
Success response
- Code:
201 Created - Body: a deposition resource.
Error response
400 Bad Request: Deposition state does not allow for editing (e.g. depositions in stateinprogress).409 Conflict: Deposition is in the process of being integrated, please wait 5 minutes before trying again.
See HTTP status codes (400 and 500 series errors) and error responses.
Discard
Discard changes in the current editing session.
curl -i -X POST https://zenodo.org/api/deposit/depositions/1234/actions/discard?access_token=ACCESS_TOKEN
import requests
r = requests.post('https://zenodo.org/api/deposit/depositions/1234/actions/discard',
params={'access_token': ACCESS_TOKEN})
HTTP Request
POST /api/deposit/depositions/:id/actions/discard
Scopes
deposit:actions
Success response
- Code:
201 Created - Body: a deposition resource.
Error response
400 Bad Request: Deposition is not being edited.
See HTTP status codes (400 and 500 series errors) and error responses.
New version
Create a new version of a deposition.
This action will create a new deposit, which will be a snapshot of the current resouce, inheriting the metadata as well as snapshot of files. The new version deposit will have a state similar to a new, unpublished deposit, most importantly its files will be modifiable as for a new deposit.
Only one unpublished new version deposit can be available at any moment, i.e.: calling new version action multiple times will have no effect, as long as the resulting new version deposit from the first call is not published or deleted.
NOTES:
- The response body of this action is NOT the new version deposit, but the original resource.
The new version deposition can be accessed through the "latest_draft" under "links" in the response body.
- The id used to create this new version has to be the id of the latest version. It is not possible to use the global id that references all the versions.
curl -i -X POST https://zenodo.org/api/deposit/depositions/1234/actions/newversion?access_token=ACCESS_TOKEN
import requests
r = requests.post('https://zenodo.org/api/deposit/depositions/1234/actions/newversion',
params={'access_token': ACCESS_TOKEN})
HTTP Request
POST /api/deposit/depositions/:id/actions/newversion
Scopes
deposit:actions
Success response
- Code:
201 Created - Body: a deposition resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses.
Records
Representation
The Records resource is used to search through published records.
List
List all open access records.
import requests
response = requests.get('https://zenodo.org/api/records',
params={'q': 'my title',
'access_token': ACCESS_TOKEN})
print(response.json())
curl -i /api/records/?access_token=ACCESS_TOKEN
HTTP Request
GET /api/records/
Query arguments
| Parameter | Required | Description |
|---|---|---|
qstring |
optional | Search query (using Elasticsearch query string syntax). |
statusstring |
optional | Filter result based on the deposit status (either draft or published) |
sortstring |
optional | Sort order (bestmatch or mostrecent). Prefix with minus to change form ascending to descending (e.g. -mostrecent). |
pageinteger |
optional | Page number for pagination. |
sizeinteger |
optional | Number of results to return per page. |
communitiesstring |
optional | Return records that are part of the specified communities. (Use of community identifier) |
typestring |
optional | Return records of the specified type. (Publication, Poster, Presentation…) |
subtypestring |
optional | Return records of the specified subtype. (Journal article, Preprint, Proposal…) |
customstring |
optional | Return records containing the specified custom keywords. (Format custom=[field_name]:field_value) |
Header
The response format of the search can be requested by specifying it in the header.
| Accept | Description |
|---|---|
application/json |
JSON |
application/vnd.zenodo.v1+json |
Zenodo |
application/marcxml+xml |
Marc XML |
application/x-bibtex |
Bibtex |
application/x-datacite+xml |
Datacite XML |
application/x-dc+xml |
Dublin Core |
Success Response
- Code:
200 OK - Body: an array of record resources.
Error Response
See HTTP status codes (400 and 500 series errors) and error responses.
Search guide
Advanced search queries can as well be performed on Zenodo website through the search box. This is documented in the search guide
Retrieve
Retrieve a single record.
curl -i https://zenodo.org/api/records/1234
import requests
r = requests.get("https://zenodo.org/api/records/1234)
HTTP Request
GET https://zenodo.org/api/records/:id
Again, the output format of the search can be specified in the header
Success response
- Code:
200 OK - Body: a record.
Error response
See HTTP status codes (400 and 500 series errors) and error responses. |
Licenses
Representation
The License resource is used for serving the license metadata that can be applied to uploaded content on Zenodo.
License
| Field | Description |
|---|---|
createdtimestamp |
Creation time of the license (in ISO8601 format). |
updatedtimestamp |
Last modification time of deposition (in ISO8601 format). |
metadataobject |
The license metadata resource |
License metadata
| Attribute | Description |
|---|---|
idstring |
Identifier for the license. Example: cc-by-nc-4.0 |
titlestring |
The name of the license Example: GNU Lesser General Public License v3.0 |
urlstring |
URL of the license Example: http://www.opensource.org/licenses/MIT |
List
Search through licenses.
import requests
response = requests.get('/api/licenses/')
print(response.json())
curl /api/licenses/
HTTP Request
GET /api/licenses/
Query arguments
| Parameter | Required | Description |
|---|---|---|
qstring |
optional | Search query (using Elasticsearch query string syntax). |
pageinteger |
optional | Page number for pagination. |
sizeinteger |
optional | Number of results to return per page. |
Success Response
- Code:
200 OK - Body: an array of license resources.
Error response
See HTTP status codes (400 and 500 series errors) and error responses. |
Retrieve
Retrieve a single license resource.
import requests
r = requests.get("/api/licenses/cc-by-nc-4.0")
curl /api/licenses/cc-by-nc-4.0
HTTP Request
GET /api/licenses/:id
Success response
- Code:
200 OK - Body: a license resource.
Error response
See HTTP status codes (400 and 500 series errors) and error responses. |
Changes
2017-10-04
- Added new optional field
versionto deposition metadata. - Added new optional field
languageto deposition metadata.
2017-06-15
- Added support for DOI versioning as part of deposit actions.
2016-09-12
- Added support for search, pagination, sorting and filtering.
- Improved speed significantly.
2015-10-06
- Added new optional field
contributorsto deposition metadata. - Added new optional field
subjectsto deposition metadata. - Added new optional subfield
gndtocreatorsin deposition metadata.
2014-12-20
- Added new relationship
isAlternateIdentifierin subfieldrelationtorelated_identifiersin deposition metadata.
2014-12-10
- Added new relationships
hasPart,isPartOf&isIdenticalToin subfieldrelationtorelated_identifiersin deposition metadata.
2014-11-20
- Added new optional subfield
orcidtocreatorsin deposition metadata.
2014-10-21
- Added new optional fields
conference_sessionandconference_session_partto deposition metadata.
2014-09-09
- Added new optional field
referencesto deposition metadata.
2014-06-13
- Authentication changed from API keys to OAuth 2.0. API key authentication is deprecated and will be phased out in October, 2014. Please use personal access tokens instead of API keys.
2013-12-18
REST API version 1.0 final release:
- Deposition actions moved from
deposit/depositions/:id/actiontodeposit/depositions/:id/actions - Added
editanddiscarddeposition action resources. - Deposition resource representation:
state: Controlled vocabulary changed.submitted: Data type changed from Timestamp to Bool.
2013-11-13
REST API initial release candidate.
OAI-PMH
Zenodo allows you to harvest our entire repository via the Open Archives Initiative Protocol for Metadata Harvesting (OAI- PMH). OAI-PMH is a widely used protocol for harvesting metadata and most popular repository software provide support for this protocol.
All metadata is licensed under Creative Commons Zero, while the data files may be either open access and subject to a license described in the metadata or closed access and not available for download.
Base URL
https://zenodo.org/oai2d
Resumption tokens
Resumption tokens are only valid for 2 minutes. In case a token expired, you will receive a 422 Unprocessable Entity HTTP error.
Rate limit
The OAI-PMH API is rated limited like the REST API - i.e. you will receive
a 429 Too Many Requests HTTP error if you exceed the limit.
Metadata formats
Metadata for each record is available in several formats. The available formats include:
oai_datacite
OAI DataCite (latest schema version) — This metadata format has been specifically established for the dissemination of DataCite records using OAI-PMH. In addition to the original DataCite metadata, this format contains several other elements describing the version of the metadata, whether it is of reference quality, and the registering datacentre. For more information about this format and its schema please see the DataCite OAI schema website.
This metadata format will always deliver metadata according to the latest available DataCite schema version.
oai_datacite3
OAI DataCite — This metadata format has been specifically established for the dissemination of DataCite records using OAI-PMH. In addition to the original DataCite v3.0 metadata, this format contains several other elements describing the version of the metadata, whether it is of reference quality, and the registering datacentre. For more information about this format and its schema please see the DataCite OAI schema web site.
datacite
DataCite (latest version) — This metadata format contains only the original DataCite metadata without additions or alterations according to the latest DataCite schema. Please note that this format is not OAI-PMH version 2.0 compliant.
datacite3
DataCite v3.0 — This metadata format contains only the original DataCite metadata without additions or alterations. The schema for this format does not exist and metadata will not validate against it. Please note that this format is not OAI-PMH version 2.0 compliant.
oai_dc
Dublin Core — only minimal metadata is included in this format. The format is exported according to the OpenAIRE Guidelines.
marc21
MARC21 — export format primarily supported for legacy reasons. Please consider using one of the other export formats as we may discontinue support for MARC21.
Sets
We support both harvesting of the entire repository as well as selective harvesting of communities.
Entire repository
In order to harvest the entire repository you make an OAI-PMH request without passing any set specification.
user-<identifier>
Community sets — allows selective harvesting of specific communities. Replace
<identifier> with the community identifier. Alternatively each community
provides a direct harvesting API link on their front-page, which includes the
correct community identifier.
If you need selective harvesting and your use case is not supported by above sets, please contact us and we may possible create a specific set for you.
Update schedule
Most updates are available immediately, some few updates are only reflected in the OAI sets once an hour.
Changes
2016-09-12
- Deprecated metadata formats
datacite3andoai_datacite3. End of life is February 2018. - Removed rate limit of 0.5 requests/second.
- Changed resumption token expiry to two minutes due to major update of our underlying repository software.
2014-03-10
- Added metadata formats
datacite3andoai_datacite3to support DataCite v3.0.
2013-05-08
Initial release of OAI-PMH API.

