Sending data from your experiment

Send data from a jsPsych experiment or plain JavaScript, and know what each response means.

jsPsych

The quickest route is the jsPsychPipe plugin: load it, generate a unique filename, and add a save trial to your timeline. The panel below is the same one on your experiment dashboard, where YOUR_EXPERIMENT_ID is already replaced with the real value — copy from there when you are ready to run.

Load the plugin, generate a unique filename, and add a save trial to your timeline.

<script src="https://unpkg.com/@jspsych-contrib/plugin-pipe"></script>
const subject_id = jsPsych.randomization.randomID(10);
const filename = `${subject_id}.csv`;

const save_data = {
  type: jsPsychPipe,
  action: "save",
  experiment_id: "YOUR_EXPERIMENT_ID",
  filename: filename,
  data_string: ()=>jsPsych.data.get().csv()
};

Use .json() and a .json filename to save as JSON instead of CSV.

The code is the same whichever storage provider you chose — your experiment never names a provider.

Plain JavaScript

You do not need jsPsych, or any library at all. The menu at the top right of the panel above switches every sample to plain JavaScript: each one is a single fetch to a DataPipe endpoint with a JSON body carrying your experiment ID, a filename, and the data as a string.

Send whatever your experiment produces — the data string is stored byte for byte, under the filename you give it.

Every field, response code, and error code, for all three participant endpoints. API reference

Saving as you go

By default DataPipe sees a session's data exactly once, when the experiment finishes. If a participant closes the tab, loses their connection, or their browser crashes at trial 199 of 200, all 199 trials are lost — DataPipe never saw any of them. On an online panel that is not a rare event.

Version 0.7 of the plugin can send each trial as it is produced. The Save as you go tab in the panel above has the code: start a session before the timeline runs, hand each trial to it from on_data_update, and pass the session to your save trial.

Three things to know before switching a live study over:

  • A completed session is unchanged. The save trial still sends your whole dataset, in your chosen format, stored under the filename you gave it. What DataPipe held during the session is deleted as soon as your submission lands.
  • An abandoned session becomes a second kind of file. DataPipe assembles the trials it received and stores them as <your filename>.partial.json — JSON even if your experiment submits CSV, because it is rebuilt from individual trials rather than from the string your experiment would have sent. Plan for that in your analysis, and treat a partial file as a participant who did not finish. Partial sessions do not count toward your session limit.
  • It cannot break your experiment. If a session cannot be started — the experiment is switched off, the participant is offline — the experiment runs and submits exactly as it would without it. The same is true of every individual trial write.

While a study is running, your experiment's dashboard shows how many participants are part-way through and how long each has been going, updating as they start, finish, or lose their connection. A participant whose connection drops is shown as Connection lost — may resume for 10 minutes, then Stopped — being recovered once DataPipe begins turning what they did into a partial file.

The trade is size: the browser build of the plugin grows from about 1 KB to about 53 KB compressed, because it carries the database client that makes this work. If your participants are on slow connections and you do not need this, the plain Save data path is still the right one.

Where staged trials live while a session is running, and how they differ from the copies DataPipe encrypts. What DataPipe stores

Filenames must be unique

Two submissions to the same experiment can never share a filename: the second one is rejected with OSF_FILE_EXISTS and is not stored. That code name is historical — the rule applies on every storage provider. Generate a fresh random ID per participant and build the filename from it, as the samples above do. Do not use a counter your experiment maintains, and do not reuse a name after a failed attempt.

DataPipe, not your storage provider, is what enforces this — and what happens to a duplicate differs by provider. Filenames, archives and your storage

Media and binary files

Base64 data collection lets you send binary files — like audio recordings, video, or images — encoded as base64 strings. DataPipe decodes the string and stores the resulting file alongside the rest of your experiment's data. Each request sends one file at a time.

Three things to know before you rely on it:

  • It has its own switch, which works independently of Accept new data. Turn on Accept base64 file uploads on the dashboard, or these requests are rejected with BASE64DATA_COLLECTION_NOT_ACTIVE — and equally, this switch keeps accepting files after you have turned off Accept new data. Turn both off when a study ends.
  • Your validation rules do not apply to it. DataPipe checks only that the string really is base64; it cannot tell what the decoded file contains, which is why the switch exists separately and why it is worth turning off outside active collection.
  • It does not count toward your session limit, and it is not blocked by one. A file upload can still arrive after an experiment has hit its cap on data submissions.

What the session cap does and does not cover. Session limits

Request size limits

DataPipe has a 32 MB limit on the size of a single request. This limit is enforced by the server infrastructure and cannot be increased. Most experiment data is well under this limit — a typical jsPsych dataset is 50 KB to 5 MB.

If you are using version 0.6.0 or later of the @jspsych-contrib/plugin-pipe plugin, request bodies are automatically compressed with gzip before sending. Text data (JSON, CSV) typically compresses by 2–10x, which effectively raises the upload limit to roughly 60–300 MB for most experiment data. Compression is enabled by default and requires no configuration.

Compression is less effective for binary data sent to the base64 endpoint — video or audio recordings — because binary data does not compress as well as text. If you need to send individual files larger than about 25 MB through the base64 endpoint, they may still exceed the limit even after compression.

If you are sending data without the plugin — calling fetch yourself — you can compress the request body with the browser's CompressionStream API and set the Content-Encoding: gzip header. The server will decompress the body automatically.

A request that is still over 32 MB never reaches DataPipe's own code — the hosting infrastructure rejects it before any endpoint runs. There is no DataPipe error response and nothing in your experiment dashboard to explain it; your fetch call gets back a bare 500 Internal Error (or a plain network failure, depending on the client), and unlike a queued 202, the data is not held anywhere for retry. If participants are hitting this, the fix is to shrink the payload — split large recordings into smaller files, lower a sampling rate, or send data more often instead of once at the end — not to retry the same request.

What the response means

In normal operation every submission gets one of three answers, and only one of them means you should do something about it.

  • 201 — stored. The file is in your storage provider.
  • 202 — accepted, not delivered yet. DataPipe is holding the data and will keep trying your provider on its own. Do not resubmit: the session is already counted, and a second submission under the same filename would be rejected as a duplicate.
  • 400 — rejected, and nothing was stored. The error field in the response body names the reason: data collection switched off, the session limit reached, a duplicate filename, or data that failed validation.

Responses from the data endpoint also carry a metadataMessage field. It reports what DataPipe did with your Psych-DS metadata; it never decides whether a submission is accepted.

The full status table, with every error code and what to do about it. Responses

Created by the developers of jsPsych ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Test environment. Data sent here is not preserved. Do not sign in with production credentials.