Skip to main content
A request is one submission of a request workflow’s form. Its status moves through:
Requests that don’t need approval start running as soon as they’re submitted. If the workflow turns off auto-run on approval, an approved request waits in approved until someone starts it with POST requests/{id}/start/. Approval itself lives on the request; the execution is a run.

POST workflows/{id}/submit/

The API equivalent of filling in the form. Permission: workflow.execute. The workflow must be active with API intake on, otherwise 409.
form_data is keyed by the form’s field ids. skip_approval needs the skip:workflow_approval scope (personal tokens) and the workflow.skip_approval permission. Response 201:
Errors: 422 with errors per field when answers don’t pass the form’s validation; 400 if the workflow isn’t a request workflow or its form can’t be loaded.

GET workflows/{id}/form-options/

Current choices for fields whose options come from job datasets (options_from in form.yml).

GET requests/

Requests you can see: on workflows you can view, ones you submitted, and ones you’re a designated approver on. Newest first, paginated.

GET requests/{id}/

approvals[].state is waiting, approved, rejected or changes_requested. capabilities says what you can do with the request now.

PATCH requests/{id}/

The submitter updates the answers while the request is open or changes_requested. The old answers are kept as a revision, approvals already given are cleared, and the request goes back to open.
Send every answer, not only the changed ones. Response 200: {"success": true, "request": {…}}. Errors: 403 if you didn’t submit it; 409 once it’s approved, running or finished, or if the workflow stopped taking API requests; 422 for invalid answers.

GET requests/{id}/activity/

Everything that happened, newest first. type is created, status_change, approval, comment or revision (the submitter updated the answers; changes lists what changed).

GET requests/{id}/comments/

POST requests/{id}/comments/

{"content": "The prod account, please."}. Anyone who can see the request can comment. Up to 5000 characters. Response 201: {"success": true, "comment": {…}}.

POST requests/{id}/cancel/

The submitter cancels a request that hasn’t started running. 409 otherwise.

POST requests/{id}/approve/

As a designated approver. notes is optional.
The last required approval starts the run (when auto_deploy_on_approval is on).

POST requests/{id}/reject/ and POST requests/{id}/request-changes/

As a designated approver. notes (the reason, or what to change) is required.
Errors for all decisions: 403 if you’re not a designated approver; 409 if the request isn’t open.

POST requests/{id}/start/

Starts a request that is approved (or needs no approval) but hasn’t run, because the workflow doesn’t run on approval automatically. Designated approvers and anyone with workflow.execute can start it. 200 with request_status; 409 if the request isn’t waiting to run; 403 without permission.

Answers on a request

  • form_data holds the answers. Answers to password fields are masked as •••••••• wherever a request is shown, including this API.
  • dataset_selections records, for each field whose options came from a job dataset, the dataset version and the full row that was picked: {"repo": {"version_id": "…", "row": {"name": "infra", "url": "…"}}}. It keeps the record accurate after that dataset version is pruned.