---
title: "Replace approver groups"
method: PUT
path: "/v3/approval_flows/{id}/replace_approver_groups"
tags: ["Approval Flows"]
---

# Replace approver groups

`PUT /v3/approval_flows/{id}/replace_approver_groups`

Wholesale-replace the ordered tiers of approvers on an existing approval flow — the V3 equivalent of rebuilding the flow's structure from an external HRIS. The flow must be in `pending` status; resolved (approved or rejected) flows cannot be modified. The new array's index becomes each group's `sort_order`, each approver entry must identify a user by `user_id`, `email`, or `employee_id`, and the same user cannot appear in more than one group. To swap a single approver inside a group without touching the rest of the flow use `PUT /v3/approver_groups/{id}/replace_approver`; to flip the flow between sequential and parallel use `PATCH /v3/approval_flows/{id}`.

## Path parameters

- `id` integer, required

## Request body

- object
  - `approver_groups` object[], required — New ordered tiers that will fully replace the flow's existing approver groups. The array's index becomes each group's `sort_order` (zero-based). The flow must be `pending`; resolved (approved or rejected) flows cannot be modified.
    - `approvals_required` integer, required — Number of approvers in this group whose approvals are needed to resolve the group as approved (the M in "M of N"). Must be at least 1 and no greater than the number of `approvers` in the group.
    - `approvers` union[], required — Users to add as approvers in this group. Each entry must identify exactly one user via `user_id`, `email`, or `employee_id`; the service resolves the identifier to a user in the caller's organization and returns 422 if any entry cannot be matched or is duplicated across groups in the same flow.
      - union
        - object
          - `email` string — Email of an existing, non-disabled user in the caller's organization.
          - `employee_id` string — External employee id (from employee data sync) of an existing, non-disabled user in the caller's organization. Useful when an HRIS holds employee ids but not Greenhouse user ids.
          - `user_id` integer, required — Id of an existing, non-disabled user in the caller's organization. References a `/v3/users` row.
        - object
          - `email` string, required — Email of an existing, non-disabled user in the caller's organization.
          - `employee_id` string — External employee id (from employee data sync) of an existing, non-disabled user in the caller's organization. Useful when an HRIS holds employee ids but not Greenhouse user ids.
          - `user_id` integer — Id of an existing, non-disabled user in the caller's organization. References a `/v3/users` row.
        - object
          - `email` string — Email of an existing, non-disabled user in the caller's organization.
          - `employee_id` string, required — External employee id (from employee data sync) of an existing, non-disabled user in the caller's organization. Useful when an HRIS holds employee ids but not Greenhouse user ids.
          - `user_id` integer — Id of an existing, non-disabled user in the caller's organization. References a `/v3/users` row.

## Response `200`

Successful

- object
  - `id` integer
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `job_id` integer — Id of the job (hiring plan) this approval flow belongs to. References a `/v3/jobs` row.
  - `offer_id` integer, nullable — Id of the specific offer this approval flow gates. Set only for `offer_candidate` flows attached to a real offer; null on the `open_job` and `offer_job` flows (which gate the job itself), and null on the `offer_candidate` prototype flow that lives on the job before any offer is created.
  - `approval_type` 'open_job' | 'offer_job' | 'offer_candidate' — What this flow approves. `open_job` gates opening the job for recruiting, `offer_job` gates allowing offers to be created on the job, and `offer_candidate` gates extending an individual offer to a candidate (one flow per offer, plus a prototype on the job).
  - `sequential` boolean — When `true`, approver groups resolve one at a time in `sort_order` — only after the current group resolves as approved are the next group's approvers asked. When `false`, all groups are activated in parallel as soon as the flow is started.
  - `version` integer — Monotonically increasing revision counter for this approval flow. Job approval flows increment when system fields (e.g., department, requisition id, openings) or custom fields marked as triggering re-approval change after the flow has started. Use this together with an approver's `version_sent` to tell whether a pending approver is responding to the current version or a stale request. Offer approval flows attached to a specific `offer_id` are always version 1.
  - `requested_by_id` integer, nullable — Id of the user who started the flow by requesting approvals (the V3 `request_approvals` endpoint, or the in-app "Request Approval" button). References a `/v3/users` row. Null until the flow has been started — approver groups exist but no emails have been sent.
  - `approval_status` 'pending' | 'rejected' | 'approved' | 'null', nullable — Denormalized terminal state of the flow, computed from the underlying approvers. `pending` while any group is still unresolved, `approved` once every group has reached its `approvals_required` threshold, `rejected` once any group has accumulated enough rejections to be unrecoverable. Updates to `sequential` and `replace_approver_groups` are only allowed while `pending`.
  - `approver_groups` object[] — Approver groups created on this flow, ordered by `sort_order`. Returned only on create/replace responses as a convenience; the canonical way to read groups for an existing flow is `/v3/approver_groups?approval_flow_ids=` and the people in each group via `/v3/approvers?approver_group_ids=`.
    - `id` integer — Id of the created approver group. References a `/v3/approver_groups` row.
    - `approvals_required` integer — Number of approvers in this group whose `approve` actions are needed to resolve the group as approved (i.e., the M in "M of N").
    - `sort_order` integer — Zero-based position of this group within the flow. When the flow is `sequential`, lower `sort_order` groups must resolve as approved before later groups become actionable.
    - `approvers` object[] — Users seeded into this group, in the order they were submitted in the request.
      - `id` integer — Id of the created approver row. References a `/v3/approvers` row.
      - `user_id` integer — Id of the user designated as an approver. References a `/v3/users` row.
      - `email` string — Email address of the designated user, echoed back for client-side display so partners do not have to round-trip to `/v3/users` after a create.

## Other responses

- `401` — Unauthorized
- `403` — Forbidden
- `422` — Unprocessable Content

---

[API](https://skmtc.dev/greenhouse/apis/auth-api.md) · [All operations](https://skmtc.dev/greenhouse/apis/auth-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/greenhouse/auth-api/revisions/9517a2e54640/schema)
