Outcome
A stage step is a Topolo Forms form or Topolo Survey survey that a pipeline stage sends each candidate who reaches it (moved there, added to the role, or applying on the job board into the entry stage): each candidate gets their own link carrying a token in the providers' reserved topolo_ctx parameter (no hidden field needed), and the submission or response (forms.submission.created, survey.response.created through Recruit's connection) is recorded on the candidate (applications.get steps[]). Lists the role's steps by stage with each placement's current status from Developers (ready, changed, unavailable, removed, access_removed); a status Developers cannot be asked for right now (or for an API key) is the last one Recruit saw.
Before you start
- Verify identity and the pinned organization context, then discover the exact action and a granted Recruit workspace.
- The required application permission is workspace:read. Hiring-team roles and record visibility are enforced separately; a workspace grant alone does not grant every Recruit action.
- Organization and workspace identity come from verified context. Pass the workspace as resourceType/resourceId, separate from action input; request-body organizationId/workspaceId values cannot select an authorized scope.
- The first authorized action can initialize an identity-only workspace mirror and invoke the configured workspace-created callback. It does not create an Auth workspace or grant new access.
Recruiters can perform the full hiring workflow. Hiring managers see their managed roles and candidates; interviewers see assigned interviews and their candidates. Workspace owners and organization administrators act as recruiters. Use team.me to read the caller's effective role and allowed actions.
Discover the target
topolo whoami --json
topolo actions get app_topolo_recruit.roles.steps.list --detail --json
topolo resources topolo-recruit --json
topolo workspaces list topolo-recruit --json
topolo actions get app_topolo_recruit.team.me --detail --json
topolo actions get app_topolo_recruit.roles.list --detail --json
Request
GET /api/roles/{id}/steps
Save input as payload.json. CLI and MCP action input includes path identifiers. The reviewed plan separates path/query fields from the HTTP body. Set RECRUIT_WORKSPACE_ID from granted resource discovery.
Inspect and test this action in the signed action console. Use its discovered schema and plan; a test response still requires the verification described below.
Input fields
| Field | Required | Type | Constraints |
|---|---|---|---|
id | Required | string | Role id from roles.list. {"minLength":1,"maxLength":64} |
Exact input schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"maxLength": 64
}
},
"required": [
"id"
],
"additionalProperties": false
}
Effects
- Reads steps; records each placement's current status.
Interpret the response
Check each step's status and respondentUrl: only ready or changed steps with a respondentUrl are sent.
The response identifier path is $.steps[].id for stage_step. Lists may be empty; an empty list is not a discovered target.
Exact success schema:
{
"type": "object",
"required": [
"roleId",
"steps"
],
"properties": {
"roleId": {
"type": "string"
},
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"roleId": {
"type": "string"
},
"stageId": {
"type": "string"
},
"reference": {
"type": "string",
"description": "topolo:<app>/<workspace>/<type>/<id>"
},
"providerAppId": {
"type": "string"
},
"providerWorkspaceId": {
"type": "string"
},
"resourceType": {
"type": "string"
},
"resourceId": {
"type": "string"
},
"resourceVersion": {
"type": [
"string",
"null"
]
},
"kind": {
"enum": [
"form",
"survey"
]
},
"title": {
"type": "string"
},
"workspaceName": {
"type": [
"string",
"null"
]
},
"respondentUrl": {
"type": [
"string",
"null"
],
"description": "The item's url from the provider's declared reference get action (e.g. forms.references.get, surveys.references.get), which personal links are built from; null unless the item is published, and the step is not sent while null."
},
"placementId": {
"type": [
"string",
"null"
]
},
"status": {
"enum": [
"ready",
"changed",
"unavailable",
"removed",
"access_removed"
]
},
"statusCheckedAt": {
"type": [
"string",
"null"
]
},
"createdBy": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
}
}
}
}
Worked examples
Actual dispatcher and migration-created SQLite or Worker handlers; Auth/workspace identity, object storage, mail and Notify dependencies are simulated. These synthetic fixtures establish no live authorization or delivery. A synthetic fixture identifier grants no access. Validate and inspect the planned request before executing. Commands with --confirm or MCP confirm:true assume the intended effect or data export has already been authorized.
Successful request
Actual dispatcher and migration-created SQLite; verified Auth/workspace context, object storage, mail and Notify dependencies are simulated. No live delivery or credential authorization is established. This complete response is a local fixture, not a deployed or delivered result.
Input · payload.json:
{
"id": "role_c7be67720b9c40b49701717e0dd52110"
}
CLI:
topolo actions validate app_topolo_recruit.roles.steps.list --data @payload.json --json
topolo actions plan app_topolo_recruit.roles.steps.list --resource-type workspace --resource-id "$RECRUIT_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_recruit.roles.steps.list --resource-type workspace --resource-id "$RECRUIT_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_recruit.roles.steps.list",
"input": {
"id": "role_c7be67720b9c40b49701717e0dd52110"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by resource discovery>"
}
}
Captured local response · HTTP 200:
{
"roleId": "role_c7be67720b9c40b49701717e0dd52110",
"steps": []
}
HTTP 200. Check each step's status and respondentUrl: only ready or changed steps with a respondentUrl are sent.
Another supported request
Actual dispatcher and migration-created SQLite; verified Auth/workspace context, object storage, mail and Notify dependencies are simulated. No live delivery or credential authorization is established. This complete response is a local fixture, not a deployed or delivered result.
Input · payload.json:
{
"id": "role_c7be67720b9c40b49701717e0dd52110"
}
CLI:
topolo actions validate app_topolo_recruit.roles.steps.list --data @payload.json --json
topolo actions plan app_topolo_recruit.roles.steps.list --resource-type workspace --resource-id "$RECRUIT_WORKSPACE_ID" --data @payload.json --json
topolo actions call app_topolo_recruit.roles.steps.list --resource-type workspace --resource-id "$RECRUIT_WORKSPACE_ID" --data @payload.json --json
MCP tool and arguments:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_recruit.roles.steps.list",
"input": {
"id": "role_c7be67720b9c40b49701717e0dd52110"
},
"resourceType": "workspace",
"resourceId": "<identifier returned by resource discovery>"
}
}
Captured local response · HTTP 200:
{
"roleId": "role_c7be67720b9c40b49701717e0dd52110",
"steps": [
{
"id": "sst_41a4b1fce57d446b8e0b1ca4adfbc5b5",
"roleId": "role_c7be67720b9c40b49701717e0dd52110",
"stageId": "stg_d1b8e67cab47499dbd95bb9597a32d77",
"reference": "topolo:app_topolo_forms/ws_forms/forms.form/frm_rtw",
"providerAppId": "app_topolo_forms",
"providerWorkspaceId": "ws_forms",
"resourceType": "forms.form",
"resourceId": "frm_rtw",
"resourceVersion": null,
"kind": "form",
"title": "Right to work check",
"workspaceName": "People team",
"respondentUrl": "https://forms.test/public/frm_rtw?lang=en",
"placementId": "plc_1",
"status": "changed",
"statusCheckedAt": "2026-10-05T09:00:00.000Z",
"createdBy": "u_admin",
"createdAt": "2026-10-05T09:00:00.000Z",
"updatedAt": "2026-10-05T09:00:00.000Z"
}
]
}
HTTP 200. Check each step's status and respondentUrl: only ready or changed steps with a respondentUrl are sent.
Refused request · not_found
Actual dispatcher and migration-created SQLite; verified Auth/workspace context, object storage, mail and Notify dependencies are simulated. No live delivery or credential authorization is established. This is a refused request; diagnose it before retrying.
Input · payload.json:
{
"id": "role_e551044d61ba4c999cbd4c4c06920ee9"
}
CLI:
topolo actions validate app_topolo_recruit.roles.steps.list --data @payload.json --json
topolo actions plan app_topolo_recruit.roles.steps.list --resource-type workspace --resource-id "$RECRUIT_WORKSPACE_ID" --data @payload.json --json
Captured local response · HTTP 404:
{
"error": {
"code": "not_found",
"message": "Role was not found in this workspace.",
"messageKey": "recruit.api.notFound.role",
"locale": "en"
}
}
HTTP 404. Preserve the exact response code and details. Do not claim success.
Refused request · hiring_team_role_required
Actual dispatcher and migration-created SQLite; verified Auth/workspace context, object storage, mail and Notify dependencies are simulated. No live delivery or credential authorization is established. This is a refused request; diagnose it before retrying.
Input · payload.json:
{
"id": "role_e551044d61ba4c999cbd4c4c06920ee9"
}
CLI:
topolo actions validate app_topolo_recruit.roles.steps.list --data @payload.json --json
topolo actions plan app_topolo_recruit.roles.steps.list --resource-type workspace --resource-id "$RECRUIT_WORKSPACE_ID" --data @payload.json --json
Captured local response · HTTP 403:
{
"error": {
"code": "hiring_team_role_required",
"message": "Your hiring-team role in this workspace does not allow this action.",
"messageKey": "recruit.api.errors.teamRoleRequired",
"locale": "en",
"details": {
"teamRole": null,
"allowedRoles": [
"recruiter",
"hiring_manager",
"interviewer"
]
}
}
}
HTTP 403. Preserve the exact response code and details. Do not claim success.
Verify the result
- Check each step's status and respondentUrl: only ready or changed steps with a respondentUrl are sent.
Errors and recovery
organization_context_required(HTTP 403): Select the organization authorized by the credential; do not send an organization id in the action input.permission_denied(HTTP 403): Grant the credential the required Recruit workspace permission.hiring_team_role_required(HTTP 403): Ask a recruiter to give the caller a hiring-team role that allows this action (team.members.set); error.details lists the allowed roles.workspace_required(HTTP 409): Create a Recruit workspace, or pass the workspace resource context.invalid_input(HTTP 422): Correct the fields named in error.details using inputSchema, then retry.not_found(HTTP 404): List roles to find a valid id. Records outside the caller's hiring-team view also answer 404.api_key_workspace_binding_required(HTTP 403): Create the API key bound to a workspace (an organization-wide key names a workspace nobody verified), then call again.workspace_required(HTTP 400): Send the workspace the key is bound to with --resource-type workspace --resource-id <workspace id> (or the X-Topolo-Resource-Type and X-Topolo-Resource-Id headers).workspace_forbidden(HTTP 403): Use a workspace the key is bound to; read the key's bindings in API key management.workspace_access_insufficient(HTTP 403): Give the key the workspace permission this action needs: workspace:read to read and workspace:write to change. A delete also needs workspace:write, because the write permission is what grants the read_write level.
Authentication or gateway failures may occur before the Recruit handler. Preserve the exact discovered service error, request id and credential context. The local fixtures do not establish live credential authorization.
Recovery boundary
Listing does not add or remove stage steps, but it can record refreshed placement status. There is no rollback for those observations; when Developers is unavailable or the caller uses an API key, the returned status may be the last one Recruit recorded.
Related actions
- Add a step from another app to a stage: Adds a Topolo Forms form or Topolo Survey survey (reference from references.search) to one of the role's stages as a stage step, at most five per stage. Each candidate who reaches the stage next (moved there, added to the role, or applying on the job board into the entry stage) gets their own link with a token in the providers' reserved topolo_ctx parameter, and the submission or response is recorded on the candidate (applications.get steps[]); candidates already in the stage are not sent it. Recruit places it in Developers (consumer kind recruit.stage.step) and reads the respondent link through the provider's reference get action. No hidden field is needed. It passes to Topolo Developers as the signed-in person: Developers checks the connection between Recruit and the provider app, the person's access to both workspaces and the link between them.
- Check a role's stage steps again: A stage step is a Topolo Forms form or Topolo Survey survey that a pipeline stage sends each candidate who reaches it (moved there, added to the role, or applying on the job board into the entry stage): each candidate gets their own link carrying a token in the providers' reserved topolo_ctx parameter (no hidden field needed), and the submission or response (forms.submission.created, survey.response.created through Recruit's connection) is recorded on the candidate (applications.get steps[]). Re-checks every step with Developers and its provider (placements.refresh): its status, title and, while the resource is reachable, its respondent link (null once unpublished, which stops it being sent). It passes to Topolo Developers as the signed-in person: Developers checks the connection between Recruit and the provider app, the person's access to both workspaces and the link between them.
Evidence
Actual dispatcher and migration-created SQLite or Worker handlers; Auth/workspace identity, object storage, mail and Notify dependencies are simulated. These synthetic fixtures establish no live authorization or delivery. Test capture provenance is retained with each fixture. API, database and integration outcomes require separate verification in the target environment.
Documentation history
- 2026-10-18: Added this action guide with reviewed request, response, permission, verification and recovery guidance from source
63171ed7c08aa066adb44cc01e64011e465302e1. Examples are retained local captures, not production execution or delivery proof. This publication includes the reviewed clarification: The same source record effects explicitly say records each placement current status, and the captured changed step contains statusCheckedAt. The read-classified action is not a universal no-state-change promise.