Update progress for a user on a content block
Updates a user’s progress (status, optional userData). userId is in the path, not the body. Scoped to your integration’s institution via Basic Auth credentials.
/content-blocks/{id}/progress/{userId}AuthorizationBasic auth · headerrequiredBasic Auth with clientId as username and clientSecret as password
idstringrequiredContent block ID
userIdstringrequiredUser ID
application/jsonstatusstringNew progress status for the user on this block
NOT_STARTEDIN_PROGRESSFINISHEDREVIEWEDuserDataobjectOptional block-type-specific progress payload (e.g. survey answers, workbench state)
forcebooleanWhen true, bypasses some validation guards when updating status
{
"status": "FINISHED",
"userData": {
"lastViewedAt": "2026-06-23T10:15:00.000Z",
"answers": {
"q1": "option_a"
}
},
"force": false
}{
"status": "IN_PROGRESS",
"userData": {}
}Updated progress
dataUpdateProgressResponserequiredShow propertiesHide properties
blockIdstringrequireduserIdstringrequiredstatusstringrequiredNOT_STARTEDIN_PROGRESSFINISHEDREVIEWEDpreviousStatusstring | nullrequiredNOT_STARTEDIN_PROGRESSFINISHEDREVIEWEDnullupdatedAtstring<date-time>requireduserDataobjectmetaResponseMetarequiredShow propertiesHide properties
requestIdstringrequiredtimestampstring<date-time>requiredversionstringrequiredv4watermarkstring<date-time>Present on GET /users?updatedSince= pages. Taken at the first page minus a 60s overlap. Bound into pagination.next_cursor. Use it as the next updatedSince after deduping by user id. Delivery is inclusive >= and at-least-once.
Bad Request
typestringrequirederrorcodestringrequiredbad_requestunauthorizedforbiddenresource_not_foundconflictvalidation_failedidempotency_key_reusedidempotency_key_in_progressservice_unavailableretryablerate_limit_exceededinternal_errortitlestringrequiredstatusintegerrequireddetailstringrequiredinstancestringerrorsobject[]Show propertiesHide properties
objectfieldstringmessagestringexistingUserIdstringPresent on 409 email or membership-code conflicts. The user id that already holds the email or code.
activeSessionobjectPresent on time-tracking start 409 when a session is already running. Stop this session, then retry start.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredconflictingLogobjectPresent on time-tracking 409 when the interval being written overlaps an existing log or open session. Start uses [punch, ∞). Stop uses [sessionStart, stop). endTime is null while that session is still open.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredendTimestring<date-time> | nullrequiredUnauthorized
typestringrequirederrorcodestringrequiredbad_requestunauthorizedforbiddenresource_not_foundconflictvalidation_failedidempotency_key_reusedidempotency_key_in_progressservice_unavailableretryablerate_limit_exceededinternal_errortitlestringrequiredstatusintegerrequireddetailstringrequiredinstancestringerrorsobject[]Show propertiesHide properties
objectfieldstringmessagestringexistingUserIdstringPresent on 409 email or membership-code conflicts. The user id that already holds the email or code.
activeSessionobjectPresent on time-tracking start 409 when a session is already running. Stop this session, then retry start.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredconflictingLogobjectPresent on time-tracking 409 when the interval being written overlaps an existing log or open session. Start uses [punch, ∞). Stop uses [sessionStart, stop). endTime is null while that session is still open.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredendTimestring<date-time> | nullrequiredForbidden
typestringrequirederrorcodestringrequiredbad_requestunauthorizedforbiddenresource_not_foundconflictvalidation_failedidempotency_key_reusedidempotency_key_in_progressservice_unavailableretryablerate_limit_exceededinternal_errortitlestringrequiredstatusintegerrequireddetailstringrequiredinstancestringerrorsobject[]Show propertiesHide properties
objectfieldstringmessagestringexistingUserIdstringPresent on 409 email or membership-code conflicts. The user id that already holds the email or code.
activeSessionobjectPresent on time-tracking start 409 when a session is already running. Stop this session, then retry start.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredconflictingLogobjectPresent on time-tracking 409 when the interval being written overlaps an existing log or open session. Start uses [punch, ∞). Stop uses [sessionStart, stop). endTime is null while that session is still open.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredendTimestring<date-time> | nullrequiredNot Found
typestringrequirederrorcodestringrequiredbad_requestunauthorizedforbiddenresource_not_foundconflictvalidation_failedidempotency_key_reusedidempotency_key_in_progressservice_unavailableretryablerate_limit_exceededinternal_errortitlestringrequiredstatusintegerrequireddetailstringrequiredinstancestringerrorsobject[]Show propertiesHide properties
objectfieldstringmessagestringexistingUserIdstringPresent on 409 email or membership-code conflicts. The user id that already holds the email or code.
activeSessionobjectPresent on time-tracking start 409 when a session is already running. Stop this session, then retry start.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredconflictingLogobjectPresent on time-tracking 409 when the interval being written overlaps an existing log or open session. Start uses [punch, ∞). Stop uses [sessionStart, stop). endTime is null while that session is still open.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredendTimestring<date-time> | nullrequiredToo Many Requests — 1000 requests per minute per institution. Includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (ISO-8601), and Retry-After (seconds).
typestringrequirederrorcodestringrequiredbad_requestunauthorizedforbiddenresource_not_foundconflictvalidation_failedidempotency_key_reusedidempotency_key_in_progressservice_unavailableretryablerate_limit_exceededinternal_errortitlestringrequiredstatusintegerrequireddetailstringrequiredinstancestringerrorsobject[]Show propertiesHide properties
objectfieldstringmessagestringexistingUserIdstringPresent on 409 email or membership-code conflicts. The user id that already holds the email or code.
activeSessionobjectPresent on time-tracking start 409 when a session is already running. Stop this session, then retry start.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredconflictingLogobjectPresent on time-tracking 409 when the interval being written overlaps an existing log or open session. Start uses [punch, ∞). Stop uses [sessionStart, stop). endTime is null while that session is still open.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredendTimestring<date-time> | nullrequiredInternal Server Error
typestringrequirederrorcodestringrequiredbad_requestunauthorizedforbiddenresource_not_foundconflictvalidation_failedidempotency_key_reusedidempotency_key_in_progressservice_unavailableretryablerate_limit_exceededinternal_errortitlestringrequiredstatusintegerrequireddetailstringrequiredinstancestringerrorsobject[]Show propertiesHide properties
objectfieldstringmessagestringexistingUserIdstringPresent on 409 email or membership-code conflicts. The user id that already holds the email or code.
activeSessionobjectPresent on time-tracking start 409 when a session is already running. Stop this session, then retry start.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredconflictingLogobjectPresent on time-tracking 409 when the interval being written overlaps an existing log or open session. Start uses [punch, ∞). Stop uses [sessionStart, stop). endTime is null while that session is still open.
Show propertiesHide properties
idstringrequiredstartTimestring<date-time>requiredendTimestring<date-time> | nullrequired