> 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.

# Collecting original data with Task Builder Collections

This cookbook covers how to gather original data from participants using Task Builder Collections. Unlike
Batches (where participants evaluate your existing data), Collections let participants **submit their own content**
such as images, files, or text responses.

## Overview

A Collection defines the pages and questions participants see. You attach it to a Prolific study, which handles
recruitment, reward, and participant targeting. The end-to-end workflow is:

1. **Define a study template**: reward, description, and participant targeting
2. **Create a collection**: define pages, instructions, and content blocks
3. **Publish the study** to start recruiting participants
4. **Monitor submissions** via the CLI or app

## Use cases

* Image or file collection (e.g. photos, documents, recordings)
* Open-ended text responses
* Multi-page surveys that gather original participant data
* Consent + submission workflows

## Prerequisites

* A Prolific researcher account with Task Builder Collections enabled
* An **API token** (see [API Fundamentals](/documentation/get-started/api-fundamentals))
* Your **workspace ID**, visible in the app URL: `app.prolific.com/researcher/workspaces/<workspace_id>/home`
* A **project ID** within your workspace, required to bill against workspace funds (see note below)
* The **Prolific CLI** installed (see step 1)

> **Note**
>
> **Workspace billing requires a project**
>
> Studies must be associated with a project to bill against workspace funds. A study created without a `project` field
> will default to your personal account balance. Find your project IDs with:
>
> ```bash
> prolific project list -w <workspace_id>
> ```

## Step-by-step guide

### Install and authenticate the Prolific CLI

The Prolific CLI lets you create collections, publish studies, and view submissions without writing API calls
directly.

```bash
gh repo clone prolific-oss/cli prolific-cli
cd prolific-cli && make build
mkdir -p ~/.local/bin && cp prolific ~/.local/bin/
cd .. && rm -rf prolific-cli
```

Configure your API token by creating `~/.config/prolific-oss/prolific.yaml`:

```yaml
prolific_token: <your_api_token>
```

Verify authentication:

```bash
prolific whoami
```

### Define your study

Create a JSON template for your study. When you publish via `collection publish`, the CLI automatically injects
`data_collection_method` and `data_collection_id`; you don't need to set these manually.

```json
{
  "name": "My Study",
  "description": "<p>Participant-facing description of your study.</p>",
  "project": "<project_id>",
  "reward": 50,
  "estimated_completion_time": 5,
  "total_available_places": 100,
  "prolific_id_option": "question",
  "completion_codes": [
    {
      "code": "MYCODE1",
      "code_type": "COMPLETED",
      "actions": [{ "action": "AUTOMATICALLY_APPROVE" }]
    }
  ],
  "device_compatibility": ["mobile", "desktop", "tablet"],
  "peripheral_requirements": [],
  "filters": [],
  "submissions_config": {
    "max_submissions_per_participant": 1
  }
}
```

**Reward and pricing:**

* `reward` is in **pence (GBP)** or **cents (USD)**
* Prolific's minimum rate is **£6 / \$8 per hour**
* To calculate a reward that fits a total budget: `reward_per_person = (budget / participants) / 1.4`
  (the 1.4 accounts for Prolific's \~40% service fee on workspace-billed studies)

**Participant targeting with filters:**

You can restrict your study to participants matching specific criteria. For example, to target pet owners:

```json
"filters": [
  {
    "filter_id": "pets",
    "selected_values": ["0", "1", "2", "3", "4", "5", "6", "7"]
  }
]
```

Browse available filters by querying the API:

```bash
curl -H "Authorization: Token <your_token>" https://api.prolific.com/api/v1/filters/
```

### Define your collection

Create a YAML file describing your collection. A collection is made up of one or more pages
(`collection_items`), each containing instructions and content blocks (`page_items`).

```yaml
# collection.yaml
workspace_id: <your_workspace_id>
name: My Collection
description: A brief description of what participants will do.
task_details:
  task_name: Task title shown to participants
  task_introduction: "<p>Brief introduction shown before participants begin.</p>"
  task_steps: "<ol><li>Step one</li><li>Step two</li></ol>"
collection_items:
  - order: 0
    title: Page title
    page_items:
      - order: 0
        type: rich_text
        content: |
          Instructions shown to participants on this page.
        content_format: markdown  # optional; defaults to html
      - order: 1
        type: file_upload
        description: Upload your file here
        accepted_file_types:
          - .jpg
          - .jpeg
          - .png
        max_file_size_mb: 10.0
        min_file_count: 1
        max_file_count: 1
```

**Supported page item types:**

Instruction types collect participant input:

| Type                             | Description                                                              |
| -------------------------------- | ------------------------------------------------------------------------ |
| `free_text`                      | Open text input from participant.                                        |
| `free_text_with_unit`            | Text input with a unit selector (e.g. kg / lbs).                         |
| `multiple_choice`                | Single or multi-select options. Set `answer_limit: 1` for single-select. |
| `multiple_choice_with_free_text` | Options with associated free-text fields.                                |
| `file_upload`                    | File submission with configurable type and size constraints.             |

Content block types display content to participants (no input collected):

| Type        | Description                                                                                      |
| ----------- | ------------------------------------------------------------------------------------------------ |
| `rich_text` | Display formatted content. Supports `markdown` or `html` via `content_format` (default: `html`). |
| `image`     | Display an image. Requires `url` (HTTPS only) and `alt_text`.                                    |

Once you're happy with your collection definition, create it:

```bash
prolific collection create -t collection.yaml
```

Save the `ID` from the response; you'll need it in the next step.

### Create a draft study

Link your collection to a study and create it in draft status for review before going live:

```bash
prolific collection publish <collection_id> -t study-template.json --draft
```

> **Note**
>
> The `-t study-template.json` flag is **required**. Without it the command has no reward, description, or
> participant count to work with and will fail.

The `--draft` flag creates the study as `UNPUBLISHED` so you can review and adjust it before participants can
see it. Save the **Study ID** from the output.

To update any fields on the draft (e.g. adjust the reward):

```bash
echo '{"reward": 60}' | prolific study update <study_id> -t -
```

All fields can be updated on a draft study. Once published, only certain fields (such as
`total_available_places`) can be changed.

### Preview and publish the study

Before going live, preview your study to check how it will appear to participants:

```bash
prolific collection publish <collection_id> -t study-template.json --preview
```

This returns a preview URL you can open in your browser to walk through the participant experience.

> **Warning**
>
> **Do not use the Prolific app to review this study.** The researcher UI is not yet configured to handle
> studies created via Collections and will crash on the review screen. Use the `--preview` flag above or the
> CLI instead.

When you're ready to go live, transition the draft study to active:

```bash
prolific study transition <study_id> -a PUBLISH
```

Once successfully published, the study's `status` will be `ACTIVE` and participants matching your filters will
begin to see it.

> **Warning**
>
> Ensure your workspace has sufficient funds before publishing. A study created without a `project` will bill
> against your personal account (which may have a £0 / \$0 balance). See the prerequisites note above.

### Monitor submissions

View incoming submissions for your study:

```bash
prolific submission list -s <study_id>
```

This shows each submission's participant ID, status, and time taken. Statuses include:

| Status            | Meaning                              |
| ----------------- | ------------------------------------ |
| `ACTIVE`          | Participant is currently in progress |
| `AWAITING REVIEW` | Completed, pending your approval     |
| `APPROVED`        | Approved and paid                    |
| `RETURNED`        | Participant returned or timed out    |

You can also view submissions in the app at:
`https://app.prolific.com/researcher/studies/<study_id>`

## Retrieving submitted data

Submitted data is available via the export API. Exports are generated asynchronously and delivered as a
presigned HTTPS URL pointing to a ZIP archive.

### Request an export

```bash
curl -X POST \
  -H "Authorization: Token <your_token>" \
  https://api.prolific.com/api/v1/data-collection/collections/<collection_id>/export
```

If the export is ready immediately (e.g. a cached result), the response is `200 OK`:

```json
{
  "status": "complete",
  "url": "https://...",
  "expires_at": "2024-01-01T12:00:00.000Z"
}
```

If generation is still in progress, the response is `202 Accepted`:

```json
{
  "status": "generating",
  "export_id": "<export_id>"
}
```

### Poll for completion

When you receive a `202`, poll using the `export_id` until `status` is `complete` or `failed`:

```bash
curl -H "Authorization: Token <your_token>" \
  https://api.prolific.com/api/v1/data-collection/collections/<collection_id>/export/<export_id>
```

Once complete, the response includes a `url` field — a presigned URL valid for 1 hour. Re-poll the `GET`
endpoint to receive a refreshed URL if it has expired. If the status is `failed`, retry by sending `POST`
again.

### Archive contents

The ZIP contains:

| File              | Description                                                   |
| ----------------- | ------------------------------------------------------------- |
| `responses.jsonl` | One JSON record per submission, keyed by instruction ID       |
| `collection.json` | Collection metadata and instruction definitions               |
| `README.md`       | Quick-start guide and pandas example                          |
| `files/`          | Uploaded files referenced by `file_upload` responses (if any) |

Each line in `responses.jsonl` has this shape:

```json
{
  "submission_id": "...",
  "participant_id": "...",
  "collection_id": "...",
  "created_at": "2024-01-01T10:00:00.000Z",
  "responses": {
    "<instruction_id>": {
      "type": "free_text",
      "description": "Instruction prompt shown to the participant",
      "value": "Participant's answer"
    }
  }
}
```

The `responses` object is keyed by instruction ID. Use `collection.json` to map instruction IDs to their
human-readable descriptions. The shape of each response entry depends on the instruction type:

| Instruction type                 | Response fields                                                      |
| -------------------------------- | -------------------------------------------------------------------- |
| `free_text`                      | `type`, `description`, `value`                                       |
| `free_text_with_unit`            | `type`, `description`, `value`, `unit`                               |
| `multiple_choice`                | `type`, `description`, `values` (array of strings)                   |
| `multiple_choice_with_free_text` | `type`, `description`, `values` (array of `{ option, explanation }`) |
| `file_upload`                    | `type`, `description`, `files` (array of `{ name, path }`)           |

For `file_upload` responses, the `path` field corresponds to the file path within the `files/` directory of the
ZIP archive.

### Working with the data (Python)

```python
import pandas as pd
import json

# Load responses
df = pd.read_json('responses.jsonl', lines=True)

# Load instruction metadata for human-readable column names
with open('collection.json') as f:
    schema = json.load(f)
id_to_label = {i['id']: i['description'] for i in schema['instructions']}

# Rename response keys from instruction IDs to descriptions
responses = df['responses'].apply(
    lambda r: {id_to_label.get(k, k): v for k, v in r.items()}
)
```

## Help & support

For questions and requests specific to using Prolific's API, you can reach our support team through
[this form](https://researcher-help.prolific.com/en/articles/476151-api-support).