Upload Custom Fields File


POST /v2/institution/custom_fields/{custom_field_id}/items/upload

The request needs to be of type multipart/form-data and have its Content-Type header set to the same value; the body of the file is sent as the form data. A typical request looks like this:

POST institution/custom_fields/{custom_field_id}/items/upload HTTP/1.1
Host: api.figshare.com
Content-Length: 975
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.5.3 CPython/2.7.10 Linux/4.1.4-1-ARCH
Connection: keep-alive
Content-Type: multipart/form-data; boundary=529448d158064de596afd8f892c84e15
Authorization: token 86bbaa5d6d51fc0ae2f2defd3a474dac77ae27179ff6d04dd37e74c531bd6ed059eda584b41356337c362a259e482eb36a34825c805344e0600bb875a77444df

Content-Disposition: form-data; name="external_file"; filename="example_file.csv"

[file content goes there]



One of the simpler examples is in python. For this to work one would need to install the requests python package.

#!/usr/bin/env python

import requests

FILE_NAME = 'example_file.csv'
API_URL = 'https://api.figshare.com/v2/account/institution/custom_fields/{custom_field_id}/items/upload'.format(custom_field_id=1)
TOKEN = '86bbaa5d6d51fc0ae2f2defd3a474dac77ae27179ff6d04dd37e74c531bd6ed059eda584b41356337c362a259e482eb36a34825c805344e0600bb875a77444df'

def main():
    headers = {"Authorization": "token " + TOKEN}
    with open(FILE_NAME, 'rb') as fin:
        files = {'external_file': (FILE_NAME, fin)}
        resp = requests.post(API_URL, files=files, headers=headers)




For java one can use apache httpcomponents:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.Throwable;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class CSVUploaderExample {
    public static void main(String[] args) {
        try {
            CSVUploaderExample ex = new CSVUploaderExample(args[0]);
        } catch (Throwable t) {

    private static final String API_URL = "https://api.figshare.com/v2/account/institution/custom_fields/1/items/upload";
    private static final String TOKEN = "86bbaa5d6d51fc0ae2f2defd3a474dac77ae27179ff6d04dd37e74c531bd6ed059eda584b41356337c362a259e482eb36a34825c805344e0600bb875a77444df";

    private String fileName = null;

    CSVUploaderExample(String fileName) {
        this.fileName = fileName;

    public void upload() throws IOException {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost uploadFile = new HttpPost(API_URL);

        uploadFile.addHeader("Authorization", "token " + TOKEN);

        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        File file = new File(fileName);

        builder.addBinaryBody("external_file", new FileInputStream(file), ContentType.TEXT_PLAIN, file.getName());

        HttpEntity multipart = builder.build();

        CloseableHttpResponse response = httpClient.execute(uploadFile);
        int status = response.getStatusLine().getStatusCode();

        System.out.println("Status code was: " + status);


For the .NET / mono users there's this snippet of code:

using System;
using System.Net.Http;
using System.IO;
using System.Threading.Tasks;

namespace CSVUploaderExample
  class MainClass
    private const String API_URL = "https://api.figshare.com/v2/account/institution/custom_fields/1/items/upload";
    private const String TOKEN = "86bbaa5d6d51fc0ae2f2defd3a474dac77ae27179ff6d04dd37e74c531bd6ed059eda584b41356337c362a259e482eb36a34825c805344e0600bb875a77444df";
    private String fileName = null;

    public static void Main (string[] args)
      MainClass app = new MainClass (args [0]);
      app.Upload ();

    MainClass(String fileName) {
      this.fileName = fileName;

    public void Upload() {
      HttpClient httpClient = new HttpClient ();
      httpClient.DefaultRequestHeaders.Add ("Authorization", "token " + MainClass.TOKEN);

      MultipartFormDataContent form = new MultipartFormDataContent ();
      using (StreamReader sr = new StreamReader (this.fileName)) {
        String content = sr.ReadToEnd ();
        byte[] data = System.Text.Encoding.UTF8.GetBytes (content);

        form.Add (new ByteArrayContent (data, 0, data.Length), "external_file", this.fileName);

      Task task = httpClient.PostAsync (MainClass.API_URL, form);
      HttpResponseMessage response = task.Result;

      Console.WriteLine ("Status code was: " + response.StatusCode);



Probably one of the most versatile ways of uploading a Custom Fields values CSV is through curl given the possibility of integrating it into any other command line utility on linux/unix.

curl -XPOST\
    -H"Authorization: token 86bbaa5d6d51fc0ae2f2defd3a474dac77ae27179ff6d04dd37e74c531bd6ed059eda584b41356337c362a259e482eb36a34825c805344e0600bb875a77444df"\


    "message": "OK",
    "code": "200"


Standard error responses

Other specific errors:

    "message": "Previous import still in progress!",
    "code": "PreviousCustomFieldUploadNotComplete"

when the feed has already been submitted within a 60 minutes span.

    "message": "You are not allowed to upload values for this custom field",
    "code": "DropdownLargeListFieldUpdateUnauthorizedError"

when the user is not authorized to make the upload

    "message": "This custom field cannot be updated via this method",
    "code": "BadRequest"

when trying to upload a file for a custom field of a different type besides dropdown_large_list.


The success response only indicates the fact that the system has understood the request, has received the file and has initiated the necessary tasks. It is not a confirmation that the file processing is complete.

The token given in the upper examples is a general Figshare API personal belonging to an admin/owner of the group the custom field has been created in (either institutional admin or group admin/owner). No other users should be able to use this endpoint (otherwise an Unauthorised error will be returned).

By default, only one file upload can be initiated every 60 minutes per portal. The enforced delay will not be automatically lifted if the custom field is deleted in the meantime. The length of this enforced delay can be customized by submitting a request to Figshare support.

The only supported file format at the moment is CSV. The first line of the file will be ignored, as it is assumed to be a header row. For all further rows, the values in all columns will be concatenated, with a single space inserted between each pair of values, and the result will be added as an item for the custom metadata field. For example, the following file content:

    header1,header2,header 3
    123,My awesome field value,456

will generate a single custom field value 123 My awesome field value 456.

Values must have a minimum of 3 characters and a maximum of 255 characters. All values outside of this interval will simply be ignored.

API feature list

The figshare api v2 is accessible at https://api.figshare.com/v2. All communication is done through https and all data is encoded as JSON.

Sending parameters

More often than not you need to send parameters to an endpoint. For GET requests these are usualy sent in the query string but for POST and PUT requests they are usually in the body of the request.

Query string

Query strings can contain parameters encoded as application/x-www-form-urlencoded. Very common for GET requests.

Example: Sending page parameter when listing articles:

GET /v2/articles?page=3 HTTP/1.1
      Host: api.figshare.com
      Authorization: token a287ab8c7ebdbe6

Request json body

POST and PUT request usualy read their params from the body of the http request. Our API only understands application/json encoded bodies.

Example: Sending search_for parameter when searching for articles:

POST /v2/articles/search HTTP/1.1
      Host: api.figshare.com
      Authorization: token a287ab8c7ebdbe6

          "search_for": "figshare"

Resource representations

Resources can be presented differently across endpoints. Usually endpoints that return a list of resources will send a lighter representation of each resource while an endpoint for an individual resource will use a more detailed and complete representation.

Representations for each resource type are documented inside each endpoint in the Body Schema section.

Blank resource fields are included in the representation as null instead of being omitted.


The v2 API supports OAuth2 access tokens, issued as described in the oauth section.

In addition to oauth access tokens, you can also use a personal token which grants you full access to your account. Personal tokens can be created and managed from the applications page at figshare.

Any of these tokens can be used to authenticate and there are 2 options to include them in requests:

GET /v2/token HTTP/1.1
      Host: api.figshare.com
      Authorization: token ACCESS_TOKEN

Example with curl:

curl -H "Authorization: token ACCESS_TOKEN" https://api.figshare.com/v2

Query param:

GET /v2/token?access_token=ACCESS_TOKEN HTTP/1.1
      Host: api.figshare.com

Example with curl:

curl https://api.figshare.com/v2?access_token=ACCESS_TOKEN


Endpoints can respond with error responses. The common error responses for all endpoints are presented below and errors specific to individual enpoints are documented along with the endpoint.

Each error response will have a specific HTTP status code and a JSON body with the following fields:

Field Description
message A human friendly message explaining the error.
code A machine friendly error code, used by the dev team to identify the error.
data An object containing extra information about the error. Documented for each error.

404 Not found

Trying to access resources that do not exist, will trigger this response from the API.

This is also returned if you try to access a resource on which you don't have a read permission.

400 Bad request

Sending a body that cannot be parsed as JSON will result in this error response.

422 Unprocessable Entity

Sending an invalid data structure in the body will trigger this error. Invalid data can be any of the following:

401 Unauthorized

This error is returned when the authorization was unsuccessfull. This can be either due to:

403 Forbidden

This response is presented whenever you try to do something which is not permitted for your current authorization. authorization info

Rate limiting

Not implemented at this point.

Conditional requests

Most responses should return an ETag header and a Last-Modified header. You can use the values of these headers to create conditional requests. We encourage to use these whenever possible.

CORS policy

The API supports CORS for AJAX requests from any origin.


This feature is available only for institutional accounts with administrative privileges.

To impersonate an account you have to include the impersonate option inside your http request.
The value for impersonate must be the account_id of the account you wish to impersonate.
You can see the accounts which can be impersonated using our account/institution/accounts endpoint.

The impersonate option must be included in the query string when using the GET and DELETE methods, and in the body when using the POST and PUT methods.

GET Impersonation example:


GET /v2/account/articles?impersonate=1000009 HTTP/1.1

Response will contain articles of the impersonated account

POST Impersonation example:


POST /v2/account/articles HTTP/1.1


    "title": "test",
    "impersonate": 1000009

Will create an article for the impersonated account