Stages
A stage is a form: a list of components — fields built on data types, plus titles, section dividers and scheduled notifications — with settings for when it becomes available to whom, its reminders, and what happens on submission. The Stages article explains those settings from the interface's point of view; this one lists the fields the API takes.
Reading stages needs access to the trial; creating, updating and deleting them needs trial.write. A locked trial refuses changes.
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/trials/<trialId>/stages |
The trial's stages, as {"stages": [...]}, in order. |
POST |
/trials/<trialId>/stages |
Create a stage. |
GET |
/stages/<stageId> |
One stage. Add ?format=pdf or ?format=docx for a blank CRF (&response=<responseId> fills the Word version in); the response has a temporary url. |
PUT |
/stages/<stageId> |
Update a stage. |
DELETE |
/stages/<stageId> |
Delete a stage. |
DELETE |
/stages?ids=<id>,<id> |
Delete several. 50 requests per minute. |
GET |
/trials/<trialId>/questionnaire-library |
The built-in questionnaires (PHQ-9, GAD-7, …) as {"questionnaires": [...]}. |
GET |
/trials/<trialId>/stage-groups |
Stage groups, as {"stageGroups": [...]}. |
POST |
/trials/<trialId>/stage-groups |
Create a stage group. |
PUT DELETE |
/stage-groups/<stageGroupId> |
Update or delete one. |
GET |
/trials/<trialId>/anchors |
Anchors, as {"anchors": [...]}. |
POST |
/trials/<trialId>/anchors |
Create an anchor. |
PUT DELETE |
/anchors/<anchorId> |
Update or delete one. |
Responses to a stage are read and written through Responses and exports.
Creating a stage
POST /trials/<trialId>/stages takes the fields below and returns the stage. Three alternatives are chosen with a query parameter:
?creationType=stageLibrarywith{"importData": {"questionnaireId": "<id from the library>"}}creates a stage from a built-in questionnaire, with its data types and scoring.?creationType=generateFromAIwith{"prompt": "..."}(up to 50,000 characters) has Scorch build one or more stages from a description — see Generating stages from a description. Returns a job.?creationType=importFromREDCapwithimportDataimports a REDCap instrument.
copyFrom with another stage's _id copies it.
Stage fields
POST /trials/<trialId>/stages and PUT /stages/<stageId>:
| Field | Type | Notes |
|---|---|---|
name |
string | 2–100 characters. %n in a recurring stage's name is replaced with the occurrence number. |
description |
string | Up to 1000 characters. |
index |
integer | Position in the list. |
enabled |
boolean | Whether participants can see it. A disabled stage is admin-only and does not count towards progress. |
adHoc |
boolean | Available on demand at any time, rather than as a timepoint. |
components |
list | The form's content — see below. |
postSubmissionText |
string | Shown after submission. Up to 3000 characters. |
allowIncompleteSubmission |
boolean | Let required fields be left blank. |
oneQuestionPerScreen, showProgressBar |
boolean | Display. |
availableToSites, availableToGroups |
list of _ids |
Restrict to sites or groups; null for all. |
isRecurring, recurringFrequency, recurringDuration |
boolean, integer, integer | Repeat every recurringFrequency days for recurringDuration days. |
recurrenceNames |
list of strings | A name for each occurrence, in order. |
enableAfter |
object | When the stage becomes available: {"type": "stage", "stage": "<stageId>", "stageRecurrence": 0, "delay": <days>} after another stage is completed, or {"type": "anchor", "anchor": "<anchorId>", "delay": <days>} after an anchor date. |
enableAtTime |
string | HH:MM:SS — the time of day it becomes available. |
availabilityWindowHours |
integer | 1–8760. Close the stage this many hours after it opens. |
exemptFromBehindStatus, behindCutoffTime |
boolean, string | Whether, and from what time, an unsubmitted stage counts as behind. |
reminders |
list | Each {"hour": <hours after opening>, "title", "body", "sendVia": ["push", "sms", "whatsapp", "email"]}. |
isAnchored, anchorSchedule |
boolean, list | Schedule occurrences from an anchor: each {"anchor": "<anchorId>", "dayOffset": <days>}. |
isPoll, pollSettings |
boolean, object | Make the stage an anonymous poll; pollSettings has requireEmail, requirePhone, verifyEmail, verifyPhone, requireConsentedEmail, requireConsentedPhone. |
customLinks |
list | Links shown with a poll: each {"id", "name", "attributes": [{"name", "value"}]}. |
onSubmitRules |
list | Actions on submission: each {"id", "conditions": [{"id", "operator", "scoreThreshold"}], "actions": [{"id", "type", "message"}]}. |
Components
Each entry in components:
| Field | Type | Notes |
|---|---|---|
id |
string | Required. Any identifier unique within the stage; keep it stable across updates so conditions keep pointing at the right component. |
type |
string | title, sectionDivider or scheduledNotification for a built-in component; omit it for a field. |
dataType |
string | The data type _id, for a field. |
title |
string | Required. The question or heading. |
description |
string | Help text under the title. |
isRequired |
boolean | |
condition |
object | Show only when another field's answer matches: {"dataType": "<dataTypeId>", "operator": "equal", "value": ...}. Operators are exists, equal, notequal, more and less, as the field's format allows; for a Likert, statement names the row to test. |
scoringRules |
list | Points for answers: each {"id", "points", "operator", "value"}. |
video |
object | A video shown with the component: {"name", "fileName": "<stored name>"}. |
notificationTitle, notificationBody, notificationDelay |
string, string, integer | For a scheduledNotification component. |
Stage groups
A stage group is a labelled set of stages (or occurrences of them) shown together in the interface.
| Field | Type | Notes |
|---|---|---|
name |
string | |
description |
string | |
colour |
string | |
index |
integer | Position. |
stages |
list | Each {"stage": "<stageId>", "recurrence": <n or null>}. |
Anchors
An anchor is a date on a participant — a surgery, a randomisation — that stages and messages can be scheduled from.
| Field | Type | Notes |
|---|---|---|
name |
string | 1–100 characters. |
description |
string | Up to 500 characters. |
assignmentRule |
object | How the date is set: {"type": "manual"} (staff set it), {"type": "participant_login"} (when the participant first signs in) or {"type": "stage_completion", "stageId": "<stageId>", "stageRecurrence": 0, "dateDataType": "<dataTypeId>"}. stageRecurrence may be null for any recurrence. dateDataType is optional. When it is set, the anchor takes the date written in that date or date-time field on the stage, rather than the time of submission, and follows later edits to it. It must name a date or date-time field on that stage. With it, dateFrom is "latest" (the default) or "first". "latest" follows the date most recently written in the field on any submission, including corrections. "first" keeps the first date once set. |
A participant's anchor dates are set with PUT /trials/<trialId>/participants/<participantId>/anchors/<anchorId> — see Participant management.