> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ravenna.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Approval templates

> Create reusable approval templates with pre-configured rounds, policies, and dynamic role-based approvers that can be imported into any ticket.

Approval templates let you define reusable multi-round approval configurations that can be imported into any ticket. Instead of manually setting up rounds and approvers each time, create a template once and apply it across tickets for consistent approval workflows.

<Info>
  Ravenna has three separate template types. Approval templates live in **Settings > Approvals**, which only organization admins can open, and cover approval rounds. For a reusable checklist of subtasks on a ticket, see [task templates](/documentation/tickets/tasks#task-templates). For pre-built automation structures, see [workflow templates](/documentation/automate/workflows/workflow-builder#templates).
</Info>

## Mental model

Approval templates are reusable blueprints for multi-round approval configurations. When applied to a ticket, the template's rounds are copied into the ticket as concrete `TicketApprovalRound` records. The template and ticket rounds maintain a lineage link via `sourceTemplateRoundId`.

***

## Template data model

| Entity | Key fields | Description |
| - | - | - |
| **ApprovalTemplate** | name, description, workspaces | The template definition |
| **ApprovalTemplateRound** | name, policy, stageIndex, approvers, approverGroups, roleBasedApprovers, filterGroups | A round within the template. Rounds sharing a `stageIndex` run in parallel when the template is applied. `filterGroups` holds an optional ticket condition filter. When it matches at apply time, the resulting ticket round is created with status `SKIPPED` instead of activating. |

Templates are organization-scoped and can be assigned to specific workspaces.

***

## Template round approver types

Each template round can have three types of approvers:

| Type | Field | Resolved when |
| - | - | - |
| **Static users** | `approvers` (User\[]) | Copied directly at apply time |
| **User groups** | `approverGroups` (UserGroup\[]) | Expanded to individual users at apply time |
| **Role-based** | `roleBasedApprovers` (String\[]) | Resolved dynamically at apply time |

### Role-based approver values

* `ticket_requester` - Resolves to the ticket's requester
* `requester_manager` (code identifier `manager_id`) - Resolves to the requester's manager. Ravenna cascades through the app-scoped integration, then the organization-wide HRIS, then the identity provider (ACCESS\_PROVIDER), and returns the first manager found. If **no** source produces a manager, the slot falls back to the ticket's workspace admins so the round always has at least one approver.
* `requester_skip_level_manager` (code identifier `skip_level_manager_id`) - Resolves strictly two levels up the manager hierarchy (requester → manager → manager's manager). Each level uses the same cascade as `requester_manager` (app-scoped integration → HRIS → identity provider). If either the direct manager or the skip-level manager cannot be resolved, the slot falls back to the ticket's workspace admins. Ravenna never substitutes the direct manager when a skip-level manager is missing.
* `access_level_owners` (code identifier `access_level_owner_id`) - Resolves to the owners of the requested access level, including every member of its owner groups. If the access level has no owners, the application's owners are used. Applies to access request workflows.

Resolution happens in `resolveTemplateRoundApprovers()`. If a role other than `requester_manager` or `requester_skip_level_manager` cannot be resolved, the approver slot is silently skipped. Those two manager roles are the only ones with a workspace-admin safety net.

***

## Apply template process

1. Delete all existing non-reset rounds on the ticket
2. For each template round (ordered by `stageIndex`):
   a. Resolve dynamic approvers (role-based + group expansion)
   b. Snapshot the template round's `filterGroups` onto the ticket round (or `null` if unset)
   c. Evaluate `filterGroups` against the ticket's hydrated field values. If they match, create the ticket round with status `SKIPPED`; otherwise create it as normal.
   d. Create `TicketApprovalRound` with `sourceTemplateRoundId` link
   e. Copy the template round's `stageIndex` onto the ticket round
3. Kickoff: activate every non-skipped round in the lowest `stageIndex` that still has a non-skipped round, set ticket approval status to IN\_PROGRESS. If every round produced by the template is `SKIPPED`, set the ticket's `approvalStatus` to APPROVED and record `approvalCompletedAt` instead of activating anything.
4. Dispatch notifications to all approvers in the first activated stage, deduping approvers who appear in more than one round of that stage

***

## Template vs ticket rounds

| Aspect | Template round | Ticket round |
| - | - | - |
| **Approver storage** | Users, groups, and role-based identifiers | Only concrete users |
| **Group handling** | Persists group IDs | Groups expanded at apply time |
| **Ordering** | `stageIndex` integer field (rounds sharing a value run in parallel) | `stageIndex` integer field (copied from the template) |
| **Lifecycle** | Static blueprint | Active lifecycle with status transitions |
| **Lineage** | Source | Links back via `sourceTemplateRoundId` |
| **Skip conditions** | `filterGroups` (ticket condition filter) | Snapshotted `filterGroups`; evaluated once at apply time to decide `SKIPPED` vs `PENDING`/`ACTIVE` |

***

## Constraints and gotchas

* Applying a template replaces all existing non-reset rounds. This is destructive.
* Template changes do not propagate to tickets that already imported the template.
* Templates are organization-scoped. Workspace assignment controls visibility, not ownership.
* If all dynamic approvers in a round fail to resolve, the round is created with no approvers, which will block the approval process, **except** when the unresolved role is `requester_manager` or `requester_skip_level_manager`. In those cases, the ticket's workspace admins are substituted as approvers so the round can proceed. The fallback is limited to those two manager roles: it does not apply to `ticket_requester` or `access_level_owners`, and it does not activate on mixed rounds where another approver (static user, group, or a manager successfully resolved from a later source in the cascade) already fills the slot.
* `requester_skip_level_manager` is strictly two levels up. If the requester's direct manager cannot be found, or the direct manager has no manager of their own, the role goes unresolved (before the workspace-admin fallback kicks in). Ravenna never substitutes the direct manager for a missing skip-level manager.
* Templates with the THRESHOLD policy are supported in the template round configuration.
* `filterGroups` on a template round is snapshotted onto the ticket round at apply time. It is evaluated once against the ticket's hydrated fields; matching conditions produce a `SKIPPED` ticket round rather than blocking approval. Later changes to the ticket do not re-evaluate an already-created round.
* If every round in the template resolves to `SKIPPED` for a given ticket, the ticket's `approvalStatus` is set to `APPROVED` and `approvalCompletedAt` is stamped. The ticket is not left in `IN_PROGRESS` with no active round.
* In a parallel stage, only the non-skipped rounds are activated. If every round sharing that `stageIndex` is skipped, the stage is treated as settled and Ravenna advances to the next stage.


## Related topics

- [Available tools](/documentation/automate/mcp/tools.md)
- [Access policies](/documentation/automate/access-provisioning/policies.md)
- [Approvals](/documentation/tickets/approvals/overview.md)
- [Get an approval template](/api/approval-templates/get-an-approval-template.md)
- [List approval templates](/api/approval-templates/list-approval-templates.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.