Zotero Server Write API
This is version 1 of the Zotero Web API. For new development, use API version 3.
This page documents the write methods of the Zotero Web API. See the Read API page for basic information on accessing the API, including possible HTTP status codes not listed here.
An API key with write access to a given library is necessary to use write methods.
To-do:
- Mappings caching (If-Modified-Since)
- Non-English type/field locales
Item Type/Field Requests
For an API client to present an editing UI to its users, it must know what combinations of Zotero item types, fields, and creator types are valid. Clients can request this data from the Zotero API.
As schema changes are currently rare, clients should cache type/field data for a period of time (e.g., one hour) without making further requests. Subsequent requests for new data should then include If-Modified-Since
headers containing the contents of the Last-Modified
header from the original response. If no changes have occurred, the server will return a 304 Not Modified
and clients should continue to use cached data for the same period of time.
User-friendly type/field names will be returned in English by default. Clients can request names in other languages by passing a locale
parameter (e.g., GET /itemTypes?locale=fr-FR
).
Hint: For manual viewing, add pprint=1
to the following requests for easier-to-read output.
Get All Item Types
GET /itemTypes If-Modified-Since: Mon, 14 Mar 2011 22:30:17 GMT
[ { "itemType" : "book", "localized" : "Book" }, { "itemType" : "note", "localized" : "Note" }, (…) ]
Common responses | |
---|---|
200 OK | |
304 Not Modified | No changes have occurred since If-Modified-Since time. |
400 Bad Request | Locale not supported. |
Get All Item Fields
GET /itemFields If-Modified-Since: Mon, 14 Mar 2011 22:30:17 GMT
[ { "field" : "title", "localized" : "Title" }, { "field" : "url", "localized" : "URL" }, (…) ]
Common responses | |
---|---|
200 OK | |
304 Not Modified | No changes have occurred since If-Modified-Since time. |
400 Bad Request | Locale not supported. |
Get All Valid Fields for an Item Type
Note: API consumers intending to write to the server should generally use /items/new combined with /itemTypes instead of this request.
GET /itemTypeFields?itemType=book If-Modified-Since: Mon, 14 Mar 2011 22:30:17 GMT
[ { "field" : "title", "localized" : "Title" }, { "field" : "abstractNote", "localized" : "Abstract" }, (…) ]
Common responses | |
---|---|
200 OK | |
304 Not Modified | No changes have occurred since If-Modified-Since time. |
400 Bad Request | Locale not supported. |
Get Valid Creator Types for an Item Type
GET /itemTypeCreatorTypes?itemType=book
[ { "creatorType" : "author", "localized" : "Author" }, { "creatorType" : "editor", "localized" : "Editor" }, (…) ]
Common responses | |
---|---|
200 OK | |
304 Not Modified | No changes have occurred since If-Modified-Since time. |
400 Bad Request | 'itemType' is unspecified or invalid; locale not supported. |
Get Localized Creator Fields
GET /creatorFields If-Modified-Since: Mon, 14 Mar 2011 22:30:17 GMT
[ { "field" : "firstName", "localized" : "First" }, { "field" : "lastName", "localized" : "Last" }, { "field" : "name", "localized" : "Name" } ]
Common responses | |
---|---|
304 Not Modified | No changes have occurred since If-Modified-Since time. |
400 Bad Request | Locale not supported. |
Get Template for a New Item
GET /items/new?itemType=book If-Modified-Since: Mon, 14 Mar 2011 22:30:17 GMT
{ "itemType" : "book", "title" : "", "creators" : [ { "creatorType" : "author", "firstName" : "", "lastName" : "" } ], "url" : "", (...), "tags" : [], "notes" : [] }
GET /items/new?itemType=note If-Modified-Since: Mon, 14 Mar 2011 22:30:17 GMT
{ "itemType" : "note", "note" : "", "tags" : [] }
Adding attachments is not yet supported.
Common responses | |
---|---|
200 OK | |
304 Not Modified | No changes have occurred since If-Modified-Since time. |
400 Bad Request | itemType is unspecified or invalid. |
Write Requests
Creating an Item
POST /users/1/items Content-Type: application/json X-Zotero-Write-Token: 19a4f01ad623aa7214f82347e3711f56
{ "items" : [ { "itemType" : "book", "title" : "My Book", "creators" : [ { "creatorType":"author", "firstName" : "Sam", "lastName" : "McAuthor" }, { "creatorType":"editor", "name" : "John T. Singlefield" } ], "tags" : [ { "tag" : "awesome" }, { "tag" : "rad", "type" : 1 } ], "notes" : [ { "itemType" : "note", "note" : "<p>What a <strong>great</strong> book!</p>" } ] } ] }
All fields other than itemType
are optional.
Note content will be treated as HTML and sanitized automatically.
Common responses | |
---|---|
201 Created | Item(s) successfully created — see example Atom response below |
400 Bad Request | Invalid type/field; unparseable JSON |
409 Conflict | The target library is locked. |
412 Precondition Failed | The provided X-Zotero-Write-Token has already been submitted. |
413 Request Entity Too Large | Too many items submitted |
Example 201 Created
response:
<?xml version="1.0"?> <feed xmlns="http://www.w3.org/2005/Atom" xmlns:zapi="http://zotero.org/ns/api"> <title>Zotero / Zotero User / Items</title> <id>http://zotero.org/users/1/items?itemKey=ABCD2345</id> <link rel="self" type="application/atom+xml" href="https://api.zotero.org/users/1/items?itemKey=ABCD2345"/> <link rel="first" type="application/atom+xml" href="https://api.zotero.org/users/1/items?itemKey=ABCD2345"/> <link rel="last" type="application/atom+xml" href="https://api.zotero.org/users/1/items?itemKey=ABCD2345"/> <zapi:totalResults>1</zapi:totalResults> <zapi:apiVersion>1</zapi:apiVersion> <updated>2010-12-17T00:18:51Z</updated> <entry> <title>My Book</title> <author> <name>Zotero User</name> <uri>http://zotero.org/zuser</uri> </author> <id>http://zotero.org/users/zuser/items/ABCD2345</id> <published>2010-12-17T00:18:51Z</published> <updated>2010-12-17T00:18:51Z</updated> <link rel="self" type="application/atom+xml" href="https://api.zotero.org/users/1/items/ABCD2345?content=json"/> <link rel="alternate" type="text/html" href="http://zotero.org/users/zuser/items/ABCD2345"/> <zapi:key>ABCD2345</zapi:key> <zapi:itemType>book</zapi:itemType> <zapi:creatorSummary>McAuthor</zapi:creatorSummary> <zapi:numChildren>1</zapi:numChildren> <zapi:numTags>2</zapi:numTags> <content type="application/json" etag="8e984e9b2a8fb560b0085b40f6c2c2b7"> { "itemType" : "book", "title" : "My Book", "creators" : [ { "creatorType" : "author", "firstName" : "Sam", "lastName" : "McAuthor" }, { "creatorType":"editor", "name" : "John T. Singlefield" } ], "tags" : [ { "tag" : "awesome" }, { "tag" : "rad", "type" : 1 } ] } </content> </entry> </feed>
Creating Multiple Items
JSON for multiple items can be passed in the items
array. A maximum of 50 items can be added in a single request.
Updating an Existing Item
First, retrieve the current version of the item, specifying JSON as the format for the Atom <content>
node:
GET /users/1/items/ABCD2345?content=json
See Creating an Item above for an example response.
Next, modify the JSON and resubmit to the server. Include the value of the <content>
node's etag
attribute in the If-Match
HTTP header:
PUT /users/1/items/ABCD2345 Content-Type: application/json If-Match: "8e984e9b2a8fb560b0085b40f6c2c2b7"
{ "itemType" : "book", "title" : "My Amazing Book", "creators" : [ { "creatorType":"author", "firstName" : "Sam", "lastName" : "McAuthor" }, { "creatorType":"editor", "name" : "John T. Singlefield" } ], "tags" : [ { "tag" : "awesome" }, { "tag" : "rad", "type" : 1 } ] }
All fields other than itemType
, creators
, and tags
are optional. If creators
and/or tags
are empty, any associated creators and/or tags will be removed from the item.
Child notes can be added only with new items. To add child notes to an existing item, POST an items
array containing note items to /users/<userID>/items/<itemKey>/children
.
PUT requests must include an If-Match
header with an ETag provided by a previous request for the item. If the item has been changed on the server since the item was retrieved, the PUT request will be rejected with a 412 Precondition Failed
error, and the most recent version of the item will have to be retrieved from the server before changes can be made.
Common responses | |
---|---|
200 OK | Same as Atom response above, but with updated data. |
400 Bad Request | Invalid type/field; unparseable JSON; client did not include ETag. |
409 Conflict | The target library is locked. |
412 Precondition Failed | The item has changed since retrieval (i.e., the provided ETag no longer matches). |
Deleting an Item
GET /users/1/items/ABCD2345?content=json DELETE /users/1/items/ABCD2345 If-Match: "8e984e9b2a8fb560b0085b40f6c2c2b7"
Common responses | |
---|---|
204 No Content | The item was deleted. |
409 Conflict | The target library is locked. |
412 Precondition Failed | The item has changed since retrieval (i.e., the provided ETag no longer matches). |
Adding Items to a Collection
POST /users/1/collections/QRST9876/items
ABCD2345 BCDE3456 CDEF4567 DEFG5678
The POST body is a space-delimited list of item keys from the same library as the collection. Existing items not specified will not be removed from the collection.
Child items cannot be added directly to collections.
Common responses | |
---|---|
204 No Content | Items were added to collection. |
400 Bad Request | Item not found in library; attempt to add child item to collection. |
409 Conflict | The target library is locked. |
Removing an Item from a Collection
DELETE /users/1/collections/QRST9876/items/ABCD2345
Common responses | |
---|---|
204 No Content | Item was removed from the collection. |
409 Conflict | The target library is locked. |
Creating a Collection
POST /users/1/collections Content-Type: application/json X-Zotero-Write-Token: 19a4f01ad623aa7214f82347e3711f56
{ "name" : "My Collection", "parent" : "QRST9876" }
Common responses | |
---|---|
201 Created | The collection was created. |
409 Conflict | The target library is locked. |
412 Precondition Failed | The provided X-Zotero-Write-Token has already been submitted. |
Updating an Existing Collection
GET /users/1/collections/RSTU8765?content=json PUT /users/1/collections/RSTU8765 Content-Type: application/json If-Match: "f0ebb2240a57f4115b3ce841d5218fa2"
{ "name" : "My Collection", "parent" : false }
Common responses | |
---|---|
200 OK | The collection was updated. |
409 Conflict | The target library is locked. |
412 Precondition Failed | The collection has changed since retrieval (i.e., the provided ETag no longer matches). |
Deleting a Collection
GET /users/1/collections/RSTU8765?content=json DELETE /users/1/collections/RSTU8765 If-Match: "f0ebb2240a57f4115b3ce841d5218fa2"
Common responses | |
---|---|
204 No Content | The collection was deleted. |
409 Conflict | The target library is locked. |
412 Precondition Failed | The collection has changed since retrieval (i.e., the provided ETag no longer matches). |
X-Zotero-Write-Token
X-Zotero-Write-Token: 19a4f01ad623aa7214f82347e3711f56
X-Zotero-Write-Token
is an optional HTTP header, containing a client-generated identifier string between 8 and 32 characters in length, that can be included with item and collection creation requests to prevent them from being processed more than once (e.g., if a user clicks a form submit button twice). The Zotero server caches write tokens for successful requests for 12 hours, and subsequent requests from the same API key using the same write token will be rejected with a 412 Precondition Failed
status code. If a request fails, the write token will not be stored.