---
title: "Workflow presets — Requests for Laravel | Roundly"
description: "Define rule, quorum and stage wiring once in config/approvals.php and open requests against it by name."
url: https://roundly-consulting.com/open-source/docs/requests-for-laravel/workflow-presets
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Requests for Laravel](https://roundly-consulting.com/open-source/docs/requests-for-laravel.md)

# Workflow presets

Reuse rule, quorum and stage wiring from config('approvals.workflows'):

```php
// config/approvals.php
'workflows' => [
    'payout' => ['rule' => 'quorum', 'quorum' => 2, 'required_approvers' => 3],
    'release' => ['stages' => [
        ['rule' => 'unanimous', 'required_approvers' => 2, 'name' => 'engineering'],
        ['rule' => 'any', 'required_approvers' => 1, 'name' => 'product'],
    ]],
],
```

Then open a request against a preset by name:

```php
// Flat preset — supply the approvers:
Requests::make()->workflow('payout')->requireApprovalsFrom([$a, $b, $c])->create();

// Staged preset — one approver group per stage:
Requests::make()->workflow('release')->stageApprovers([[$eng1, $eng2], [$product]])->create();
```

- Flat presets take the approver models passed to requireApprovalsFrom(); a bare id is refused with InvalidApprover.
- Staged presets take one approver group per stage through stageApprovers().
- A workflow takes precedence over stages() and the flat approver list.
- For staged presets the preset’s reject\_on\_stage\_rejection applies, not the builder’s rejectOnStageRejection().
- An unknown or malformed preset throws the engine’s UnknownWorkflowException.

## Preset expiry and the request deadline

A preset’s round expires with the request: the request’s expires\_at (from expiresAt() or default\_ttl) replaces the preset’s own expiry for that round, every stage of a staged preset included — on create and on the fresh round a reopen() opens. A request with no deadline keeps the preset’s expiry, or none:

```php
// 'payout' => [..., 'expiry' => 3600]
Requests::make()->workflow('payout')->requireApprovalsFrom([$a])->expiresAt(now()->addDays(7))->create(); // round expires in 7 days
Requests::make()->workflow('payout')->requireApprovalsFrom([$a])->create();                               // no deadline: round expires in 1 hour
```

## Preset keys

| Key | Applies to | Meaning |
| --- | --- | --- |
| `rule` | flat preset, each stage | unanimous, quorum, any or weighted (default unanimous). |
| `quorum` | flat preset, each stage | Integer threshold for quorum / weighted. |
| `required_approvers` | flat preset, each stage | How many approvers the rule counts; mandatory and positive for every stage. |
| `name` | each stage | Stage name, read back through currentStage()->name. |
| `stages` | staged preset | Non-empty list of stage arrays — its presence makes the preset staged. |
| `reject_on_stage_rejection` | staged preset | Whether a rejected stage rejects the whole request (default true). |
| `expiry` | any preset | Seconds until the engine’s approval round lapses — used only when the request has no deadline of its own; otherwise the round takes the request’s expires\_at. |

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/requests-for-laravel.md)
