> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.prolific.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.prolific.com/_mcp/server.

# Get Started: Running AI Task Builder Batches via Prolific's API

# What you'll accomplish

* Upload raw datapoints (e.g., text, image URLs) into an **AI Task Builder Dataset**
* Create an **AI Task Builder Batch** and attach **Instructions**
* Convert your dataset into **tasks** and wait until the batch is **READY**
* Create and **publish a Prolific study** that references the batch
* Pull **annotated responses** from the batch

For detailed reference documentation, see:

* [Working with Batches](/api-reference/ai-task-builder/batches)
* [Working with Datasets](/api-reference/ai-task-builder/datasets)
* [Instructions](/api-reference/ai-task-builder/instructions)

# Prerequisites

* Your **workspace\_id**
* Your **API token** (`Authorization: Token ...`)
* Decide how many **tasks per participant** you want to show (via `tasks_per_group`)
* Decide your **study** settings (reward, sample size, timing, targeting)

# Step-by-step guide

## Create a Dataset

Create a container that will hold the datapoints participants will annotate.

### Request

POST [https://api.prolific.com/api/v1/data-collection/datasets](https://api.prolific.com/api/v1/data-collection/datasets)

```curl
curl -X POST https://api.prolific.com/api/v1/data-collection/datasets \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "name": "Customer Feedback Dataset",
  "workspace_id": "6278acb09062db3b35bcbeb0"
}'
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/datasets"

payload = {
    "name": "Customer Feedback Dataset",
    "workspace_id": "6278acb09062db3b35bcbeb0"
}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/datasets';
const options = {
  method: 'POST',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{"name":"Customer Feedback Dataset","workspace_id":"6278acb09062db3b35bcbeb0"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/datasets"

	payload := strings.NewReader("{\n  \"name\": \"Customer Feedback Dataset\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/datasets")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"name\": \"Customer Feedback Dataset\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.prolific.com/api/v1/data-collection/datasets")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"name\": \"Customer Feedback Dataset\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.prolific.com/api/v1/data-collection/datasets', [
  'body' => '{
  "name": "Customer Feedback Dataset",
  "workspace_id": "6278acb09062db3b35bcbeb0"
}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/datasets");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"name\": \"Customer Feedback Dataset\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "name": "Customer Feedback Dataset",
  "workspace_id": "6278acb09062db3b35bcbeb0"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/datasets")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

Response will include `id` (your `dataset_id`) and `status` (one of `UNINITIALISED|PROCESSING|READY|ERROR`).

## Request An Upload URL For Your Data

Upload one or more files (CSV format) that contain the datapoints.

### Request

GET [https://api.prolific.com/api/v1/data-collection/datasets/\{dataset\_id}/upload-url/\{filename}](https://api.prolific.com/api/v1/data-collection/datasets/\{dataset_id}/upload-url/\{filename})

```curl
curl https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json"
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename"

payload = {}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.get(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename';
const options = {
  method: 'GET',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("GET", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/datasets/dataset_id/upload-url/filename")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

**The response body will be structured as follows**

```json
{
    "upload_url": "string",
    "expires_at": "string",  // ISO-8601 DateTime string
    "http_method": "string", // PUT in all instances
    "dataset_id": "string"
}
```

## Upload Your Data (files → dataset)

Upload the file containing your datapoints.

```bash
curl -X PUT "UPLOAD_URL_FROM_PREVIOUS_STEP" --data-binary "@{path_to_file}"
```

**Poll status** until the dataset is processed:

### Request

GET [https://api.prolific.com/api/v1/data-collection/datasets/\{dataset\_id}](https://api.prolific.com/api/v1/data-collection/datasets/\{dataset_id})

```curl
curl https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json"
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d"

payload = {}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.get(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d';
const options = {
  method: 'GET',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("GET", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/datasets/0192a3b5-e8f9-7a0b-1c2d-3e4f5a6b7c8d")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

```bash
{"status": "READY"} # (wait for READY)
```

For advanced dataset options including metadata columns and custom task grouping, see [Working with Datasets](/api-reference/ai-task-builder/datasets).

## Create a Batch

Batches bind datasets + instructions into something you can attach to a Prolific study.

You can also include task details here with introductions and steps.
`task_introduction` and `task_steps` fields support basic HTML.

### Request

POST [https://api.prolific.com/api/v1/data-collection/batches](https://api.prolific.com/api/v1/data-collection/batches)

**`Batch Create Example`**

```curl Batch Create Example
curl -X POST https://api.prolific.com/api/v1/data-collection/batches \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "name": "Sentiment Analysis Batch",
  "workspace_id": "6278acb09062db3b35bcbeb0",
  "task_details": {
    "task_name": "Evaluate Product Reviews",
    "task_introduction": "<p>In this task, you will analyze product reviews and categorize their sentiment.</p>",
    "task_steps": "<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>"
  },
  "dataset_id": "1234acb09999db4b99bcded1"
}'
```

**`Batch Create Example`**

```python Batch Create Example
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches"

payload = {
    "name": "Sentiment Analysis Batch",
    "workspace_id": "6278acb09062db3b35bcbeb0",
    "task_details": {
        "task_name": "Evaluate Product Reviews",
        "task_introduction": "<p>In this task, you will analyze product reviews and categorize their sentiment.</p>",
        "task_steps": "<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>"
    },
    "dataset_id": "1234acb09999db4b99bcded1"
}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Batch Create Example`**

```javascript Batch Create Example
const url = 'https://api.prolific.com/api/v1/data-collection/batches';
const options = {
  method: 'POST',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{"name":"Sentiment Analysis Batch","workspace_id":"6278acb09062db3b35bcbeb0","task_details":{"task_name":"Evaluate Product Reviews","task_introduction":"<p>In this task, you will analyze product reviews and categorize their sentiment.</p>","task_steps":"<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>"},"dataset_id":"1234acb09999db4b99bcded1"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Batch Create Example`**

```go Batch Create Example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches"

	payload := strings.NewReader("{\n  \"name\": \"Sentiment Analysis Batch\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\",\n  \"task_details\": {\n    \"task_name\": \"Evaluate Product Reviews\",\n    \"task_introduction\": \"<p>In this task, you will analyze product reviews and categorize their sentiment.</p>\",\n    \"task_steps\": \"<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>\"\n  },\n  \"dataset_id\": \"1234acb09999db4b99bcded1\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Batch Create Example`**

```ruby Batch Create Example
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"name\": \"Sentiment Analysis Batch\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\",\n  \"task_details\": {\n    \"task_name\": \"Evaluate Product Reviews\",\n    \"task_introduction\": \"<p>In this task, you will analyze product reviews and categorize their sentiment.</p>\",\n    \"task_steps\": \"<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>\"\n  },\n  \"dataset_id\": \"1234acb09999db4b99bcded1\"\n}"

response = http.request(request)
puts response.read_body
```

**`Batch Create Example`**

```java Batch Create Example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.prolific.com/api/v1/data-collection/batches")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"name\": \"Sentiment Analysis Batch\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\",\n  \"task_details\": {\n    \"task_name\": \"Evaluate Product Reviews\",\n    \"task_introduction\": \"<p>In this task, you will analyze product reviews and categorize their sentiment.</p>\",\n    \"task_steps\": \"<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>\"\n  },\n  \"dataset_id\": \"1234acb09999db4b99bcded1\"\n}")
  .asString();
```

**`Batch Create Example`**

```php Batch Create Example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.prolific.com/api/v1/data-collection/batches', [
  'body' => '{
  "name": "Sentiment Analysis Batch",
  "workspace_id": "6278acb09062db3b35bcbeb0",
  "task_details": {
    "task_name": "Evaluate Product Reviews",
    "task_introduction": "<p>In this task, you will analyze product reviews and categorize their sentiment.</p>",
    "task_steps": "<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>"
  },
  "dataset_id": "1234acb09999db4b99bcded1"
}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Batch Create Example`**

```csharp Batch Create Example
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"name\": \"Sentiment Analysis Batch\",\n  \"workspace_id\": \"6278acb09062db3b35bcbeb0\",\n  \"task_details\": {\n    \"task_name\": \"Evaluate Product Reviews\",\n    \"task_introduction\": \"<p>In this task, you will analyze product reviews and categorize their sentiment.</p>\",\n    \"task_steps\": \"<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>\"\n  },\n  \"dataset_id\": \"1234acb09999db4b99bcded1\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Batch Create Example`**

```swift Batch Create Example
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "name": "Sentiment Analysis Batch",
  "workspace_id": "6278acb09062db3b35bcbeb0",
  "task_details": [
    "task_name": "Evaluate Product Reviews",
    "task_introduction": "<p>In this task, you will analyze product reviews and categorize their sentiment.</p>",
    "task_steps": "<ol><li>Read each review carefully</li><li>Select the appropriate sentiment</li><li>Provide a brief explanation</li></ol>"
  ],
  "dataset_id": "1234acb09999db4b99bcded1"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

(**Note:** `dataset_id` is optional at creation time and can be added later via update, but must be provided before setup.)

Save the returned `id` as `BATCH_ID`.

### Update a Batch (optional)

You can update a batch's name, task details, or associated dataset after creation.

### Request

PATCH [https://api.prolific.com/api/v1/data-collection/batches/\{batch\_id}](https://api.prolific.com/api/v1/data-collection/batches/\{batch_id})

```curl
curl -X PATCH https://api.prolific.com/api/v1/data-collection/batches/batch_id \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{}'
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches/batch_id"

payload = {}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.patch(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/batches/batch_id';
const options = {
  method: 'PATCH',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches/batch_id"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("PATCH", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches/batch_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.patch("https://api.prolific.com/api/v1/data-collection/batches/batch_id")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://api.prolific.com/api/v1/data-collection/batches/batch_id', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches/batch_id");
var request = new RestRequest(Method.PATCH);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches/batch_id")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

All fields are optional - include only what you want to update.

### Duplicate a Batch (optional)

You can create a copy of an existing batch, either with or without its dataset.

#### Duplicate with the same dataset (dataset is shared, not copied)

```bash
curl -X POST https://api.prolific.com/api/v1/data-collection/batches/BATCH_ID/duplicate \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Copy of My Batch"
  }'
```

#### Duplicate without a dataset (requires new upload)

```bash
curl -X POST https://api.prolific.com/api/v1/data-collection/batches/BATCH_ID/duplicate \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Copy of My Batch",
    "upload_new_dataset": true
  }'
```

If `name` is omitted, the duplicate will be named `[Original Batch Name] (Copy)`.

**Note:** When duplicating with a dataset, both batches will reference the same dataset - it is not duplicated.

## Add Instructions to the Batch

You can create **multiple** instructions. Types supported:

* `multiple_choice` — selection from options (use `answer_limit` for single or multi-select)
* `free_text` — open-ended text input
* `multiple_choice_with_free_text` — selection with associated free text fields
* `file_upload` — file submission

For full schema details, see [Instructions](/api-reference/ai-task-builder/instructions).

### Request

POST [https://api.prolific.com/api/v1/data-collection/batches/\{batch\_id}/instructions](https://api.prolific.com/api/v1/data-collection/batches/\{batch_id}/instructions)

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```curl AI Task Builder_CreateTaskBuilderInstructions_example
curl -X POST https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "instructions": [
    {
      "type": "multiple_choice",
      "description": "Choose the LLM response which is more accurate.",
      "answer_limit": 1,
      "options": [
        {
          "label": "Response 1",
          "value": "response1"
        },
        {
          "label": "Response 2",
          "value": "response2"
        }
      ]
    },
    {
      "type": "free_text",
      "description": "Please share the reasons for your choice.",
      "placeholder_text_input": "e.g. I chose this response because..."
    },
    {
      "type": "multiple_choice_with_free_text",
      "description": "Rate each aspect and explain your reasoning.",
      "answer_limit": -1,
      "options": [
        {
          "label": "Good",
          "value": "accuracy_good",
          "heading": "Accuracy"
        },
        {
          "label": "Needs improvement",
          "value": "accuracy_poor",
          "heading": "Accuracy"
        }
      ]
    },
    {
      "type": "free_text_with_unit",
      "description": "What is your height?",
      "unit_options": [
        {
          "label": "Centimeters",
          "value": "cm",
          "validation": {
            "type": "number",
            "min": 50,
            "max": 300
          }
        },
        {
          "label": "Feet",
          "value": "ft",
          "validation": {
            "type": "number",
            "min": 1,
            "max": 9
          }
        }
      ],
      "unit_position": "suffix"
    },
    {
      "type": "file_upload",
      "description": "Upload a photo of the item",
      "accepted_file_types": [
        ".jpg",
        ".jpeg",
        ".png"
      ],
      "max_file_size_mb": 10,
      "min_file_count": 1,
      "max_file_count": 3
    }
  ]
}'
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```python AI Task Builder_CreateTaskBuilderInstructions_example
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions"

payload = { "instructions": [
        {
            "type": "multiple_choice",
            "description": "Choose the LLM response which is more accurate.",
            "answer_limit": 1,
            "options": [
                {
                    "label": "Response 1",
                    "value": "response1"
                },
                {
                    "label": "Response 2",
                    "value": "response2"
                }
            ]
        },
        {
            "type": "free_text",
            "description": "Please share the reasons for your choice.",
            "placeholder_text_input": "e.g. I chose this response because..."
        },
        {
            "type": "multiple_choice_with_free_text",
            "description": "Rate each aspect and explain your reasoning.",
            "answer_limit": -1,
            "options": [
                {
                    "label": "Good",
                    "value": "accuracy_good",
                    "heading": "Accuracy"
                },
                {
                    "label": "Needs improvement",
                    "value": "accuracy_poor",
                    "heading": "Accuracy"
                }
            ]
        },
        {
            "type": "free_text_with_unit",
            "description": "What is your height?",
            "unit_options": [
                {
                    "label": "Centimeters",
                    "value": "cm",
                    "validation": {
                        "type": "number",
                        "min": 50,
                        "max": 300
                    }
                },
                {
                    "label": "Feet",
                    "value": "ft",
                    "validation": {
                        "type": "number",
                        "min": 1,
                        "max": 9
                    }
                }
            ],
            "unit_position": "suffix"
        },
        {
            "type": "file_upload",
            "description": "Upload a photo of the item",
            "accepted_file_types": [".jpg", ".jpeg", ".png"],
            "max_file_size_mb": 10,
            "min_file_count": 1,
            "max_file_count": 3
        }
    ] }
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```javascript AI Task Builder_CreateTaskBuilderInstructions_example
const url = 'https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions';
const options = {
  method: 'POST',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{"instructions":[{"type":"multiple_choice","description":"Choose the LLM response which is more accurate.","answer_limit":1,"options":[{"label":"Response 1","value":"response1"},{"label":"Response 2","value":"response2"}]},{"type":"free_text","description":"Please share the reasons for your choice.","placeholder_text_input":"e.g. I chose this response because..."},{"type":"multiple_choice_with_free_text","description":"Rate each aspect and explain your reasoning.","answer_limit":-1,"options":[{"label":"Good","value":"accuracy_good","heading":"Accuracy"},{"label":"Needs improvement","value":"accuracy_poor","heading":"Accuracy"}]},{"type":"free_text_with_unit","description":"What is your height?","unit_options":[{"label":"Centimeters","value":"cm","validation":{"type":"number","min":50,"max":300}},{"label":"Feet","value":"ft","validation":{"type":"number","min":1,"max":9}}],"unit_position":"suffix"},{"type":"file_upload","description":"Upload a photo of the item","accepted_file_types":[".jpg",".jpeg",".png"],"max_file_size_mb":10,"min_file_count":1,"max_file_count":3}]}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```go AI Task Builder_CreateTaskBuilderInstructions_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions"

	payload := strings.NewReader("{\n  \"instructions\": [\n    {\n      \"type\": \"multiple_choice\",\n      \"description\": \"Choose the LLM response which is more accurate.\",\n      \"answer_limit\": 1,\n      \"options\": [\n        {\n          \"label\": \"Response 1\",\n          \"value\": \"response1\"\n        },\n        {\n          \"label\": \"Response 2\",\n          \"value\": \"response2\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text\",\n      \"description\": \"Please share the reasons for your choice.\",\n      \"placeholder_text_input\": \"e.g. I chose this response because...\"\n    },\n    {\n      \"type\": \"multiple_choice_with_free_text\",\n      \"description\": \"Rate each aspect and explain your reasoning.\",\n      \"answer_limit\": -1,\n      \"options\": [\n        {\n          \"label\": \"Good\",\n          \"value\": \"accuracy_good\",\n          \"heading\": \"Accuracy\"\n        },\n        {\n          \"label\": \"Needs improvement\",\n          \"value\": \"accuracy_poor\",\n          \"heading\": \"Accuracy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text_with_unit\",\n      \"description\": \"What is your height?\",\n      \"unit_options\": [\n        {\n          \"label\": \"Centimeters\",\n          \"value\": \"cm\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 50,\n            \"max\": 300\n          }\n        },\n        {\n          \"label\": \"Feet\",\n          \"value\": \"ft\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 1,\n            \"max\": 9\n          }\n        }\n      ],\n      \"unit_position\": \"suffix\"\n    },\n    {\n      \"type\": \"file_upload\",\n      \"description\": \"Upload a photo of the item\",\n      \"accepted_file_types\": [\n        \".jpg\",\n        \".jpeg\",\n        \".png\"\n      ],\n      \"max_file_size_mb\": 10,\n      \"min_file_count\": 1,\n      \"max_file_count\": 3\n    }\n  ]\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```ruby AI Task Builder_CreateTaskBuilderInstructions_example
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"instructions\": [\n    {\n      \"type\": \"multiple_choice\",\n      \"description\": \"Choose the LLM response which is more accurate.\",\n      \"answer_limit\": 1,\n      \"options\": [\n        {\n          \"label\": \"Response 1\",\n          \"value\": \"response1\"\n        },\n        {\n          \"label\": \"Response 2\",\n          \"value\": \"response2\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text\",\n      \"description\": \"Please share the reasons for your choice.\",\n      \"placeholder_text_input\": \"e.g. I chose this response because...\"\n    },\n    {\n      \"type\": \"multiple_choice_with_free_text\",\n      \"description\": \"Rate each aspect and explain your reasoning.\",\n      \"answer_limit\": -1,\n      \"options\": [\n        {\n          \"label\": \"Good\",\n          \"value\": \"accuracy_good\",\n          \"heading\": \"Accuracy\"\n        },\n        {\n          \"label\": \"Needs improvement\",\n          \"value\": \"accuracy_poor\",\n          \"heading\": \"Accuracy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text_with_unit\",\n      \"description\": \"What is your height?\",\n      \"unit_options\": [\n        {\n          \"label\": \"Centimeters\",\n          \"value\": \"cm\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 50,\n            \"max\": 300\n          }\n        },\n        {\n          \"label\": \"Feet\",\n          \"value\": \"ft\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 1,\n            \"max\": 9\n          }\n        }\n      ],\n      \"unit_position\": \"suffix\"\n    },\n    {\n      \"type\": \"file_upload\",\n      \"description\": \"Upload a photo of the item\",\n      \"accepted_file_types\": [\n        \".jpg\",\n        \".jpeg\",\n        \".png\"\n      ],\n      \"max_file_size_mb\": 10,\n      \"min_file_count\": 1,\n      \"max_file_count\": 3\n    }\n  ]\n}"

response = http.request(request)
puts response.read_body
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```java AI Task Builder_CreateTaskBuilderInstructions_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"instructions\": [\n    {\n      \"type\": \"multiple_choice\",\n      \"description\": \"Choose the LLM response which is more accurate.\",\n      \"answer_limit\": 1,\n      \"options\": [\n        {\n          \"label\": \"Response 1\",\n          \"value\": \"response1\"\n        },\n        {\n          \"label\": \"Response 2\",\n          \"value\": \"response2\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text\",\n      \"description\": \"Please share the reasons for your choice.\",\n      \"placeholder_text_input\": \"e.g. I chose this response because...\"\n    },\n    {\n      \"type\": \"multiple_choice_with_free_text\",\n      \"description\": \"Rate each aspect and explain your reasoning.\",\n      \"answer_limit\": -1,\n      \"options\": [\n        {\n          \"label\": \"Good\",\n          \"value\": \"accuracy_good\",\n          \"heading\": \"Accuracy\"\n        },\n        {\n          \"label\": \"Needs improvement\",\n          \"value\": \"accuracy_poor\",\n          \"heading\": \"Accuracy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text_with_unit\",\n      \"description\": \"What is your height?\",\n      \"unit_options\": [\n        {\n          \"label\": \"Centimeters\",\n          \"value\": \"cm\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 50,\n            \"max\": 300\n          }\n        },\n        {\n          \"label\": \"Feet\",\n          \"value\": \"ft\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 1,\n            \"max\": 9\n          }\n        }\n      ],\n      \"unit_position\": \"suffix\"\n    },\n    {\n      \"type\": \"file_upload\",\n      \"description\": \"Upload a photo of the item\",\n      \"accepted_file_types\": [\n        \".jpg\",\n        \".jpeg\",\n        \".png\"\n      ],\n      \"max_file_size_mb\": 10,\n      \"min_file_count\": 1,\n      \"max_file_count\": 3\n    }\n  ]\n}")
  .asString();
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```php AI Task Builder_CreateTaskBuilderInstructions_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions', [
  'body' => '{
  "instructions": [
    {
      "type": "multiple_choice",
      "description": "Choose the LLM response which is more accurate.",
      "answer_limit": 1,
      "options": [
        {
          "label": "Response 1",
          "value": "response1"
        },
        {
          "label": "Response 2",
          "value": "response2"
        }
      ]
    },
    {
      "type": "free_text",
      "description": "Please share the reasons for your choice.",
      "placeholder_text_input": "e.g. I chose this response because..."
    },
    {
      "type": "multiple_choice_with_free_text",
      "description": "Rate each aspect and explain your reasoning.",
      "answer_limit": -1,
      "options": [
        {
          "label": "Good",
          "value": "accuracy_good",
          "heading": "Accuracy"
        },
        {
          "label": "Needs improvement",
          "value": "accuracy_poor",
          "heading": "Accuracy"
        }
      ]
    },
    {
      "type": "free_text_with_unit",
      "description": "What is your height?",
      "unit_options": [
        {
          "label": "Centimeters",
          "value": "cm",
          "validation": {
            "type": "number",
            "min": 50,
            "max": 300
          }
        },
        {
          "label": "Feet",
          "value": "ft",
          "validation": {
            "type": "number",
            "min": 1,
            "max": 9
          }
        }
      ],
      "unit_position": "suffix"
    },
    {
      "type": "file_upload",
      "description": "Upload a photo of the item",
      "accepted_file_types": [
        ".jpg",
        ".jpeg",
        ".png"
      ],
      "max_file_size_mb": 10,
      "min_file_count": 1,
      "max_file_count": 3
    }
  ]
}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```csharp AI Task Builder_CreateTaskBuilderInstructions_example
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"instructions\": [\n    {\n      \"type\": \"multiple_choice\",\n      \"description\": \"Choose the LLM response which is more accurate.\",\n      \"answer_limit\": 1,\n      \"options\": [\n        {\n          \"label\": \"Response 1\",\n          \"value\": \"response1\"\n        },\n        {\n          \"label\": \"Response 2\",\n          \"value\": \"response2\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text\",\n      \"description\": \"Please share the reasons for your choice.\",\n      \"placeholder_text_input\": \"e.g. I chose this response because...\"\n    },\n    {\n      \"type\": \"multiple_choice_with_free_text\",\n      \"description\": \"Rate each aspect and explain your reasoning.\",\n      \"answer_limit\": -1,\n      \"options\": [\n        {\n          \"label\": \"Good\",\n          \"value\": \"accuracy_good\",\n          \"heading\": \"Accuracy\"\n        },\n        {\n          \"label\": \"Needs improvement\",\n          \"value\": \"accuracy_poor\",\n          \"heading\": \"Accuracy\"\n        }\n      ]\n    },\n    {\n      \"type\": \"free_text_with_unit\",\n      \"description\": \"What is your height?\",\n      \"unit_options\": [\n        {\n          \"label\": \"Centimeters\",\n          \"value\": \"cm\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 50,\n            \"max\": 300\n          }\n        },\n        {\n          \"label\": \"Feet\",\n          \"value\": \"ft\",\n          \"validation\": {\n            \"type\": \"number\",\n            \"min\": 1,\n            \"max\": 9\n          }\n        }\n      ],\n      \"unit_position\": \"suffix\"\n    },\n    {\n      \"type\": \"file_upload\",\n      \"description\": \"Upload a photo of the item\",\n      \"accepted_file_types\": [\n        \".jpg\",\n        \".jpeg\",\n        \".png\"\n      ],\n      \"max_file_size_mb\": 10,\n      \"min_file_count\": 1,\n      \"max_file_count\": 3\n    }\n  ]\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`AI Task Builder_CreateTaskBuilderInstructions_example`**

```swift AI Task Builder_CreateTaskBuilderInstructions_example
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = ["instructions": [
    [
      "type": "multiple_choice",
      "description": "Choose the LLM response which is more accurate.",
      "answer_limit": 1,
      "options": [
        [
          "label": "Response 1",
          "value": "response1"
        ],
        [
          "label": "Response 2",
          "value": "response2"
        ]
      ]
    ],
    [
      "type": "free_text",
      "description": "Please share the reasons for your choice.",
      "placeholder_text_input": "e.g. I chose this response because..."
    ],
    [
      "type": "multiple_choice_with_free_text",
      "description": "Rate each aspect and explain your reasoning.",
      "answer_limit": -1,
      "options": [
        [
          "label": "Good",
          "value": "accuracy_good",
          "heading": "Accuracy"
        ],
        [
          "label": "Needs improvement",
          "value": "accuracy_poor",
          "heading": "Accuracy"
        ]
      ]
    ],
    [
      "type": "free_text_with_unit",
      "description": "What is your height?",
      "unit_options": [
        [
          "label": "Centimeters",
          "value": "cm",
          "validation": [
            "type": "number",
            "min": 50,
            "max": 300
          ]
        ],
        [
          "label": "Feet",
          "value": "ft",
          "validation": [
            "type": "number",
            "min": 1,
            "max": 9
          ]
        ]
      ],
      "unit_position": "suffix"
    ],
    [
      "type": "file_upload",
      "description": "Upload a photo of the item",
      "accepted_file_types": [".jpg", ".jpeg", ".png"],
      "max_file_size_mb": 10,
      "min_file_count": 1,
      "max_file_count": 3
    ]
  ]] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches/5f7b5e9a-3f3c-4b3e-8f1a-1a2b3c4d5e6f/instructions")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

(You can later **PUT** the same endpoint to update instructions -
please include the complete payload as it will replace all instructions on the batch, or **GET** it to read them back.)

## Set Up the Batch (build tasks, set tasks per participant)

Configure how datapoints become tasks and how many tasks each participant gets.

### Request

POST [https://api.prolific.com/api/v1/data-collection/batches/\{batch\_id}/setup](https://api.prolific.com/api/v1/data-collection/batches/\{batch_id}/setup)

```curl
curl -X POST https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{}'
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup"

payload = {}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup';
const options = {
  method: 'POST',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches/batch_id/setup")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

**Note:** The dataset must be in `READY` status before running the setup endpoint.

Now **poll batch status** until it's **READY**:

### Request

GET [https://api.prolific.com/api/v1/data-collection/batches/\{batch\_id}](https://api.prolific.com/api/v1/data-collection/batches/\{batch_id})

```curl
curl https://api.prolific.com/api/v1/data-collection/batches/batch_id \
     -H "Authorization: Token <token>"
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches/batch_id"

headers = {"Authorization": "Token <token>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/batches/batch_id';
const options = {method: 'GET', headers: {Authorization: 'Token <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches/batch_id"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Token <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches/batch_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Token <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.prolific.com/api/v1/data-collection/batches/batch_id")
  .header("Authorization", "Token <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.prolific.com/api/v1/data-collection/batches/batch_id', [
  'headers' => [
    'Authorization' => 'Token <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches/batch_id");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Token <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Token <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches/batch_id")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

```bash
{"status":"READY"} # (possible values: UNINITIALISED|PROCESSING|READY|ERROR)
```

## Create a Prolific Study that References the Batch

When the batch is **READY**, create a standard study but include these two fields:

* `"data_collection_method": "AI_TASK_BUILDER_BATCH"`
* `"data_collection_id": "BATCH_ID"`

### Request

POST [https://api.prolific.com/api/v1/studies/](https://api.prolific.com/api/v1/studies/)

**`study_with_allow_list`**

```curl study_with_allow_list
curl -X POST https://api.prolific.com/api/v1/studies/ \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "name": "Study about API'\''s for selected participants",
  "description": "This study aims to determine how to make a good public API",
  "external_study_url": "https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}",
  "prolific_id_option": "url_parameters",
  "total_available_places": 30,
  "estimated_completion_time": 5,
  "reward": 13,
  "internal_name": "WIT-2022 Study about API'\''s version 2",
  "completion_codes": [
    {
      "code": "ABC123",
      "code_type": "COMPLETED",
      "actions": [
        {
          "action": "AUTOMATICALLY_APPROVE"
        }
      ]
    },
    {
      "code": "DEF234",
      "code_type": "FOLLOW_UP_STUDY",
      "actions": [
        {
          "action": "AUTOMATICALLY_APPROVE"
        },
        {
          "action": "ADD_TO_PARTICIPANT_GROUP",
          "participant_group": "619e049f7648a4e1f8f3645b"
        }
      ]
    }
  ],
  "device_compatibility": [
    "mobile",
    "desktop",
    "tablet"
  ],
  "peripheral_requirements": [],
  "filters": [
    {
      "filter_id": "custom_allowlist",
      "selected_values": [
        "619e049f7648a4e1f8f3645b"
      ]
    }
  ],
  "submissions_config": {
    "max_submissions_per_participant": 1
  },
  "completion_code": "ABC123"
}'
```

**`study_with_allow_list`**

```python study_with_allow_list
import requests

url = "https://api.prolific.com/api/v1/studies/"

payload = {
    "name": "Study about API's for selected participants",
    "description": "This study aims to determine how to make a good public API",
    "external_study_url": "https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}",
    "prolific_id_option": "url_parameters",
    "total_available_places": 30,
    "estimated_completion_time": 5,
    "reward": 13,
    "internal_name": "WIT-2022 Study about API's version 2",
    "completion_codes": [
        {
            "code": "ABC123",
            "code_type": "COMPLETED",
            "actions": [{ "action": "AUTOMATICALLY_APPROVE" }]
        },
        {
            "code": "DEF234",
            "code_type": "FOLLOW_UP_STUDY",
            "actions": [
                { "action": "AUTOMATICALLY_APPROVE" },
                {
                    "action": "ADD_TO_PARTICIPANT_GROUP",
                    "participant_group": "619e049f7648a4e1f8f3645b"
                }
            ]
        }
    ],
    "device_compatibility": ["mobile", "desktop", "tablet"],
    "peripheral_requirements": [],
    "filters": [
        {
            "filter_id": "custom_allowlist",
            "selected_values": ["619e049f7648a4e1f8f3645b"]
        }
    ],
    "submissions_config": { "max_submissions_per_participant": 1 },
    "completion_code": "ABC123"
}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`study_with_allow_list`**

```javascript study_with_allow_list
const url = 'https://api.prolific.com/api/v1/studies/';
const options = {
  method: 'POST',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{"name":"Study about API\'s for selected participants","description":"This study aims to determine how to make a good public API","external_study_url":"https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}","prolific_id_option":"url_parameters","total_available_places":30,"estimated_completion_time":5,"reward":13,"internal_name":"WIT-2022 Study about API\'s version 2","completion_codes":[{"code":"ABC123","code_type":"COMPLETED","actions":[{"action":"AUTOMATICALLY_APPROVE"}]},{"code":"DEF234","code_type":"FOLLOW_UP_STUDY","actions":[{"action":"AUTOMATICALLY_APPROVE"},{"action":"ADD_TO_PARTICIPANT_GROUP","participant_group":"619e049f7648a4e1f8f3645b"}]}],"device_compatibility":["mobile","desktop","tablet"],"peripheral_requirements":[],"filters":[{"filter_id":"custom_allowlist","selected_values":["619e049f7648a4e1f8f3645b"]}],"submissions_config":{"max_submissions_per_participant":1},"completion_code":"ABC123"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`study_with_allow_list`**

```go study_with_allow_list
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/studies/"

	payload := strings.NewReader("{\n  \"name\": \"Study about API's for selected participants\",\n  \"description\": \"This study aims to determine how to make a good public API\",\n  \"external_study_url\": \"https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}\",\n  \"prolific_id_option\": \"url_parameters\",\n  \"total_available_places\": 30,\n  \"estimated_completion_time\": 5,\n  \"reward\": 13,\n  \"internal_name\": \"WIT-2022 Study about API's version 2\",\n  \"completion_codes\": [\n    {\n      \"code\": \"ABC123\",\n      \"code_type\": \"COMPLETED\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        }\n      ]\n    },\n    {\n      \"code\": \"DEF234\",\n      \"code_type\": \"FOLLOW_UP_STUDY\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        },\n        {\n          \"action\": \"ADD_TO_PARTICIPANT_GROUP\",\n          \"participant_group\": \"619e049f7648a4e1f8f3645b\"\n        }\n      ]\n    }\n  ],\n  \"device_compatibility\": [\n    \"mobile\",\n    \"desktop\",\n    \"tablet\"\n  ],\n  \"peripheral_requirements\": [],\n  \"filters\": [\n    {\n      \"filter_id\": \"custom_allowlist\",\n      \"selected_values\": [\n        \"619e049f7648a4e1f8f3645b\"\n      ]\n    }\n  ],\n  \"submissions_config\": {\n    \"max_submissions_per_participant\": 1\n  },\n  \"completion_code\": \"ABC123\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`study_with_allow_list`**

```ruby study_with_allow_list
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/studies/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"name\": \"Study about API's for selected participants\",\n  \"description\": \"This study aims to determine how to make a good public API\",\n  \"external_study_url\": \"https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}\",\n  \"prolific_id_option\": \"url_parameters\",\n  \"total_available_places\": 30,\n  \"estimated_completion_time\": 5,\n  \"reward\": 13,\n  \"internal_name\": \"WIT-2022 Study about API's version 2\",\n  \"completion_codes\": [\n    {\n      \"code\": \"ABC123\",\n      \"code_type\": \"COMPLETED\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        }\n      ]\n    },\n    {\n      \"code\": \"DEF234\",\n      \"code_type\": \"FOLLOW_UP_STUDY\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        },\n        {\n          \"action\": \"ADD_TO_PARTICIPANT_GROUP\",\n          \"participant_group\": \"619e049f7648a4e1f8f3645b\"\n        }\n      ]\n    }\n  ],\n  \"device_compatibility\": [\n    \"mobile\",\n    \"desktop\",\n    \"tablet\"\n  ],\n  \"peripheral_requirements\": [],\n  \"filters\": [\n    {\n      \"filter_id\": \"custom_allowlist\",\n      \"selected_values\": [\n        \"619e049f7648a4e1f8f3645b\"\n      ]\n    }\n  ],\n  \"submissions_config\": {\n    \"max_submissions_per_participant\": 1\n  },\n  \"completion_code\": \"ABC123\"\n}"

response = http.request(request)
puts response.read_body
```

**`study_with_allow_list`**

```java study_with_allow_list
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.prolific.com/api/v1/studies/")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"name\": \"Study about API's for selected participants\",\n  \"description\": \"This study aims to determine how to make a good public API\",\n  \"external_study_url\": \"https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}\",\n  \"prolific_id_option\": \"url_parameters\",\n  \"total_available_places\": 30,\n  \"estimated_completion_time\": 5,\n  \"reward\": 13,\n  \"internal_name\": \"WIT-2022 Study about API's version 2\",\n  \"completion_codes\": [\n    {\n      \"code\": \"ABC123\",\n      \"code_type\": \"COMPLETED\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        }\n      ]\n    },\n    {\n      \"code\": \"DEF234\",\n      \"code_type\": \"FOLLOW_UP_STUDY\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        },\n        {\n          \"action\": \"ADD_TO_PARTICIPANT_GROUP\",\n          \"participant_group\": \"619e049f7648a4e1f8f3645b\"\n        }\n      ]\n    }\n  ],\n  \"device_compatibility\": [\n    \"mobile\",\n    \"desktop\",\n    \"tablet\"\n  ],\n  \"peripheral_requirements\": [],\n  \"filters\": [\n    {\n      \"filter_id\": \"custom_allowlist\",\n      \"selected_values\": [\n        \"619e049f7648a4e1f8f3645b\"\n      ]\n    }\n  ],\n  \"submissions_config\": {\n    \"max_submissions_per_participant\": 1\n  },\n  \"completion_code\": \"ABC123\"\n}")
  .asString();
```

**`study_with_allow_list`**

```php study_with_allow_list
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.prolific.com/api/v1/studies/', [
  'body' => '{
  "name": "Study about API\'s for selected participants",
  "description": "This study aims to determine how to make a good public API",
  "external_study_url": "https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}",
  "prolific_id_option": "url_parameters",
  "total_available_places": 30,
  "estimated_completion_time": 5,
  "reward": 13,
  "internal_name": "WIT-2022 Study about API\'s version 2",
  "completion_codes": [
    {
      "code": "ABC123",
      "code_type": "COMPLETED",
      "actions": [
        {
          "action": "AUTOMATICALLY_APPROVE"
        }
      ]
    },
    {
      "code": "DEF234",
      "code_type": "FOLLOW_UP_STUDY",
      "actions": [
        {
          "action": "AUTOMATICALLY_APPROVE"
        },
        {
          "action": "ADD_TO_PARTICIPANT_GROUP",
          "participant_group": "619e049f7648a4e1f8f3645b"
        }
      ]
    }
  ],
  "device_compatibility": [
    "mobile",
    "desktop",
    "tablet"
  ],
  "peripheral_requirements": [],
  "filters": [
    {
      "filter_id": "custom_allowlist",
      "selected_values": [
        "619e049f7648a4e1f8f3645b"
      ]
    }
  ],
  "submissions_config": {
    "max_submissions_per_participant": 1
  },
  "completion_code": "ABC123"
}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`study_with_allow_list`**

```csharp study_with_allow_list
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/studies/");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"name\": \"Study about API's for selected participants\",\n  \"description\": \"This study aims to determine how to make a good public API\",\n  \"external_study_url\": \"https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}\",\n  \"prolific_id_option\": \"url_parameters\",\n  \"total_available_places\": 30,\n  \"estimated_completion_time\": 5,\n  \"reward\": 13,\n  \"internal_name\": \"WIT-2022 Study about API's version 2\",\n  \"completion_codes\": [\n    {\n      \"code\": \"ABC123\",\n      \"code_type\": \"COMPLETED\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        }\n      ]\n    },\n    {\n      \"code\": \"DEF234\",\n      \"code_type\": \"FOLLOW_UP_STUDY\",\n      \"actions\": [\n        {\n          \"action\": \"AUTOMATICALLY_APPROVE\"\n        },\n        {\n          \"action\": \"ADD_TO_PARTICIPANT_GROUP\",\n          \"participant_group\": \"619e049f7648a4e1f8f3645b\"\n        }\n      ]\n    }\n  ],\n  \"device_compatibility\": [\n    \"mobile\",\n    \"desktop\",\n    \"tablet\"\n  ],\n  \"peripheral_requirements\": [],\n  \"filters\": [\n    {\n      \"filter_id\": \"custom_allowlist\",\n      \"selected_values\": [\n        \"619e049f7648a4e1f8f3645b\"\n      ]\n    }\n  ],\n  \"submissions_config\": {\n    \"max_submissions_per_participant\": 1\n  },\n  \"completion_code\": \"ABC123\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`study_with_allow_list`**

```swift study_with_allow_list
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "name": "Study about API's for selected participants",
  "description": "This study aims to determine how to make a good public API",
  "external_study_url": "https://eggs-experriment.com?participant={{%PROLIFIC_PID%}}",
  "prolific_id_option": "url_parameters",
  "total_available_places": 30,
  "estimated_completion_time": 5,
  "reward": 13,
  "internal_name": "WIT-2022 Study about API's version 2",
  "completion_codes": [
    [
      "code": "ABC123",
      "code_type": "COMPLETED",
      "actions": [["action": "AUTOMATICALLY_APPROVE"]]
    ],
    [
      "code": "DEF234",
      "code_type": "FOLLOW_UP_STUDY",
      "actions": [
        ["action": "AUTOMATICALLY_APPROVE"],
        [
          "action": "ADD_TO_PARTICIPANT_GROUP",
          "participant_group": "619e049f7648a4e1f8f3645b"
        ]
      ]
    ]
  ],
  "device_compatibility": ["mobile", "desktop", "tablet"],
  "peripheral_requirements": [],
  "filters": [
    [
      "filter_id": "custom_allowlist",
      "selected_values": ["619e049f7648a4e1f8f3645b"]
    ]
  ],
  "submissions_config": ["max_submissions_per_participant": 1],
  "completion_code": "ABC123"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/studies/")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

## Publish the Study

### Request

POST [https://api.prolific.com/api/v1/studies/\{id}/transition/](https://api.prolific.com/api/v1/studies/\{id}/transition/)

**`Publish a draft study`**

```curl Publish a draft study
curl -X POST https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/ \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json" \
     -d '{
  "action": "PUBLISH"
}'
```

**`Publish a draft study`**

```python Publish a draft study
import requests

url = "https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/"

payload = { "action": "PUBLISH" }
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Publish a draft study`**

```javascript Publish a draft study
const url = 'https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/';
const options = {
  method: 'POST',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{"action":"PUBLISH"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Publish a draft study`**

```go Publish a draft study
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/"

	payload := strings.NewReader("{\n  \"action\": \"PUBLISH\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Publish a draft study`**

```ruby Publish a draft study
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"action\": \"PUBLISH\"\n}"

response = http.request(request)
puts response.read_body
```

**`Publish a draft study`**

```java Publish a draft study
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"action\": \"PUBLISH\"\n}")
  .asString();
```

**`Publish a draft study`**

```php Publish a draft study
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/', [
  'body' => '{
  "action": "PUBLISH"
}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

**`Publish a draft study`**

```csharp Publish a draft study
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"action\": \"PUBLISH\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Publish a draft study`**

```swift Publish a draft study
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = ["action": "PUBLISH"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/studies/60d9aadeb86739de712faee0/transition/")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

(Other actions available include `PAUSE`, `START` (resume), and `STOP`.)

## Retrieve Annotated Responses

There are two ways to retrieve responses once participants have completed their tasks.

### Option 1: JSON responses

Get individual responses as JSON, useful for processing programmatically or streaming results as they come in.

### Request

GET [https://api.prolific.com/api/v1/data-collection/batches/\{batch\_id}/responses](https://api.prolific.com/api/v1/data-collection/batches/\{batch_id}/responses)

```curl
curl https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json"
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses"

payload = {}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.get(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses';
const options = {
  method: 'GET',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("GET", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches/batch_id/responses")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

```json
{
  "results": [
    {
      "id": "01997d0c-34ab-748a-b6e3-104288f7a1bf",
      "batch_id": "01997d05-8689-72a8-b980-3f930729f28a",
      "participant_id": "6862a1a367ad476b8601fa2a",
      "submission_id": "68d43c57a56e9439d5d1e93e",
      "task_id": "84cc7c99-9097-5c0f-8052-65382273ace5",
      "response": {
        "instruction_id": "01997d05-8f20-734f-ad19-c82e279b5118",
        "type": "free_text",
        "answer": [
          { "value": "abc" }
        ]
      },
      "created_at": "2025-09-24T18:46:15.979Z"
    }
  ],
  "meta": {
    "count": 1
  }
}
```

### Option 2: CSV report

Download a CSV report containing your original data with response columns appended.

### Request

GET [https://api.prolific.com/api/v1/data-collection/batches/\{batch\_id}/report/](https://api.prolific.com/api/v1/data-collection/batches/\{batch_id}/report/)

```curl
curl https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/ \
     -H "Authorization: Token <token>" \
     -H "Content-Type: application/json"
```

```python
import requests

url = "https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/"

payload = {}
headers = {
    "Authorization": "Token <token>",
    "Content-Type": "application/json"
}

response = requests.get(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/';
const options = {
  method: 'GET',
  headers: {Authorization: 'Token <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("GET", url, payload)

	req.Header.Add("Authorization", "Token <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Token <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/")
  .header("Authorization", "Token <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Token <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Token <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Token <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.prolific.com/api/v1/data-collection/batches/batch_id/report/")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

This returns a presigned URL to download the CSV:

```json
{
  "url": "https://...",
  "expires_at": "2025-01-20T10:17:34.949Z",
  "http_method": "GET"
}
```

Use the `url` to download your annotated dataset.

# Operational Notes & Tips

* **Statuses**: Datasets and Batches both progress through `UNINITIALISED → PROCESSING → READY` (or `ERROR`).
  Don't attach a batch to a study until it's `READY`.
* **Instructions**: You can mix multiple instruction types within the same batch
  (e.g., two `multiple_choice` plus one `free_text`).
* **`tasks_per_group`**: Controls how many tasks a single participant receives in one "sitting"
  (this is what will be classed as a single Submission on Prolific).
  Increase to reduce study overhead and per-task price dispersion; decrease if tasks are long.
* **Targeting & Reward**: As with any Prolific study, all participants share the same targeting and reward.
* Once a batch has been set up (step 6) you can no longer edit its instructions.
* **Dataset Requirements**: Datasets do not need to be in READY status when creating, updating, or duplicating batches.
  However, the dataset **must** be in READY status before running the setup endpoint.
* **Batch Duplication**: When duplicating a batch with a dataset, the dataset is shared between both batches, not duplicated.
  If you need separate datasets, use `upload_new_dataset: true`.