API access

Use API keys to download survey JSON and results, upload a new draft version, publish it, and retrieve its participant link. Open Account settings → API keys to create a named key. Copy the secret when it appears; it is shown only once. Revoke a key there when it is no longer needed.

A user key can access all surveys owned by its researcher. A survey key can access only its selected survey, including that survey's drafts and published versions. Collaborator access and administrator privileges do not expand API key access. Keys cannot create other keys. A revoked key stops working on the next request; publication requests already accepted remain durable work.

Send the key in an HTTP header, never in a URL:

export SURVEY_API_KEY='your-key'
export SURVEY_BASE_URL='https://your-survey-host'
curl -H "Authorization: Bearer $SURVEY_API_KEY" \
  "$SURVEY_BASE_URL/api/v1/surveys"

Every API response uses Cache-Control: no-store. Keep keys and downloaded results out of shared scripts and source control.

Find surveys and versions

Method Path Result
GET /api/v1/surveys Accessible surveys, with id and title
GET /api/v1/surveys/{survey_id} Survey details, drafts, and published versions
GET /api/v1/surveys/{survey_id}/versions/{version_id}/project.json Portable authored JSON for a draft or publication
GET /api/v1/surveys/{survey_id}/versions/{version_id}/results.csv Results for a published version
GET /api/v1/surveys/{survey_id}/versions/{version_id}/results.metadata.json Column descriptions for those results

Use a root survey's id in {survey_id}. Use an id from its drafts or versions list in {version_id}. Each published version includes participant_url. Required URL parameters still need to be supplied by your recruitment process; see URL parameters.

The participant URL follows the same publication rules as Studio. Reusing a URL points it at the latest publication using that URL. It does not pin participation to an older version. Choose url_mode: "new" when publishing if the new publication should have a separate link.

Upload a new version

Start with JSON downloaded from the API or Studio. It must use the portable survey-project/1 format. See projects and survey JSON.

curl --fail-with-body \
  -H "Authorization: Bearer $SURVEY_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @survey-project.json \
  "$SURVEY_BASE_URL/api/v1/surveys/SURVEY_ID/versions"

A successful upload returns HTTP 201 with the new draft's id, survey_id, version_number, and status: "draft". It creates a separate draft inside the existing survey and inherits that survey's participant-data deletion schedule. Existing drafts, published snapshots, responses, and the shared project title are retained. Publication remains a separate step. The upload limit is 16 MiB.

Invalid documents return HTTP 422:

{
  "error": {
    "code": "validation_failed",
    "message": "Survey JSON could not be accepted.",
    "issues": [
      {
        "path": ["project", "content", "groups"],
        "code": "invalid_shape",
        "message": "Expected a list.",
        "suggestion": "Use an array at this path."
      }
    ]
  }
}

The example illustrates the response structure; messages and codes depend on the validation failure. path is an array of object keys and zero-based list indices. Fix the indicated field or reference and submit the document again. A failed upload creates no draft version. Syntax, document shape, supported component types, and semantic references are checked; passing upload validation does not bypass publication checks.

Publish and get the participant URL

curl --fail-with-body \
  -H "Authorization: Bearer $SURVEY_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"url_mode":"reuse"}' \
  "$SURVEY_BASE_URL/api/v1/surveys/SURVEY_ID/versions/DRAFT_ID/publish"

The JSON body can be {} (reuse the current URL), {"url_mode":"reuse"}, or {"url_mode":"new"}. The endpoint returns HTTP 202 with request_id, phase, and status_url. Its Location header also gives that status URL.

Poll GET {status_url} with the same bearer header until phase is published or failed. Publication first synchronizes open editors, then validates and stores the immutable snapshot. A temporary database failure leaves the request available for retry by the application; acceptance does not mean publication has succeeded.

When published, the status response includes version with its id, version_number, and participant_url. When failed, it includes error_kind and validation feedback. Correct the draft, then submit a new publication request. Publishing never bypasses the existing survey validation or participant-data retention requirements.

HTTP errors

Status Meaning
401 Missing, invalid, or revoked bearer key
404 Missing survey/version/request, or outside the key's access
409 Version is locked, broken, or currently synchronizing publication
413 Upload exceeds 16 MiB
415 POST body requires Content-Type: application/json
422 Invalid survey JSON or publication options; read the feedback
500 Operation could not complete; retry later

Errors use {"error":{"code":"...","message":"..."}}, with issues for survey validation failures. A lost HTTP response can occur after a write commits: refresh survey details before retrying an upload, since each accepted upload creates another draft. Repeating publish while the same draft is synchronizing returns its active publication request.

Confirm action