---
title: "Routing rules"
description: "Send the notification email to different addresses, and the person to a different page, based on their answers."
---

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

# Routing rules

Routing rules change where a submission goes based on its answers. Each rule has a list of conditions, and when a submission meets all of them the rule can:

- add addresses to the [notification email](https://docs.getquickforms.com/email/#notification-email), or replace its recipients
- send the person to a different page after submitting

For example, send sales enquiries to your sales team and thank them on a sales page, and copy anything that mentions "urgent" to whoever is on call.

## Settings

Rules live in `settings.routing.rules`, a list of up to 20 rules.

```json title="settings.routing"
{
  "rules": [
    {
      "name": "Sales",
      "conditions": [
        { "field": "topic", "operator": "equals", "value": "sales" }
      ],
      "notify_emails": ["sales@example.com"],
      "notify_mode": "replace",
      "redirect_url": "https://example.com/sales-thanks"
    },
    {
      "name": "Urgent",
      "conditions": [
        { "field": "message", "operator": "contains", "value": "urgent" }
      ],
      "notify_emails": ["oncall@example.com"]
    }
  ]
}
```

| Key | Type | Notes |
| --- | --- | --- |
| `name` | string or null | A label for the rule, up to 80 characters. |
| `conditions` | array | Required, up to 10. Every condition must match for the rule to apply. An empty list always matches. |
| `conditions.*.field` | string | Required. Must be one of the form's field names. |
| `conditions.*.operator` | string | Required. One of the [operators](#operators). |
| `conditions.*.value` | string or null | Up to 500 characters. Not used by `is_set` and `is_empty`. |
| `notify_emails` | array | Up to 10 email addresses. |
| `notify_mode` | string | `add` (the default) or `replace`. See [notification recipients](#notification-recipients). |
| `redirect_url` | string or null | An `http` or `https` URL. See [redirects](#redirects). |

Set them in the form's settings, for example over the [API](https://docs.getquickforms.com/api/):

```bash title="Add routing rules"
curl -X PATCH https://YOUR-QUICKFORMS-HOST/api/v1/forms/FORM_ID \
  -H "Authorization: Bearer $QUICKFORMS_TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"settings": {"routing": {"rules": [{"name": "Sales", "conditions": [{"field": "topic", "operator": "equals", "value": "sales"}], "notify_emails": ["sales@example.com"], "notify_mode": "replace"}]}}}'
```

Sending `settings.routing.rules` replaces the whole list rather than merging into it.

### Validation

A condition on a field the form doesn't have gets a `422` on that condition, for example `settings.routing.rules.0.conditions.0.field`, with "Pick one of the form's fields." An unknown operator, an invalid email in `notify_emails` or a `redirect_url` that isn't an `http` or `https` URL also gets a `422`.

## Operators

Conditions compare the field's answer with `value`.

| Operator | Matches when |
| --- | --- |
| `equals` | The answer is `value`. Case-insensitive for single answers. |
| `not_equals` | The answer is not `value`. |
| `contains` | The answer contains `value`, case-insensitive. Never matches when `value` is empty. |
| `is_set` | The field has an answer. |
| `is_empty` | The field has no answer. |

How answers are compared:

- **Fields with several answers**, such as checkboxes: `equals` matches when `value` is one of the chosen options, and `not_equals` when it isn't. This comparison is case-sensitive. `contains` looks in the answers joined with `, `.
- **Yes/no answers**: a ticked checkbox counts as `yes` and an unticked one as empty, so use `equals` with `yes`, or `is_set` and `is_empty`.
- **Missing fields** count as empty.

The same conditions are used by [destinations](https://docs.getquickforms.com/destinations/).

## Notification recipients

The notification starts with its usual recipients: `settings.notify.emails`, or the team owner when that list is empty. Then every matching rule is applied in order:

- `add` appends the rule's `notify_emails` to the recipients so far.
- `replace` swaps the recipients so far for the rule's `notify_emails`.

A rule with no `notify_emails` doesn't change the recipients. Duplicate addresses are sent one email. Because rules run in order, a later `add` rule adds to whatever an earlier `replace` rule left.

With the two rules above:

| Submission | Notification goes to |
| --- | --- |
| `topic` is `sales` | `sales@example.com` |
| `topic` is `support` and `message` contains "urgent" | The form's own recipients and `oncall@example.com` |
| `topic` is `sales` and `message` contains "urgent" | `sales@example.com` and `oncall@example.com` |
| Neither rule matches | The form's own recipients |

If the notification is switched off with `settings.notify.enabled: false`, routing rules don't send one either. Rules only change the notification email: the autoresponder, the form webhook and destinations are not affected.

## Redirects

The first matching rule with a `redirect_url` takes the place of the form's `settings.redirect_url` for that submission.

- HTML form posts get a `303` redirect to it.
- JSON clients get it as `redirect` in the response:

  ```json title="201 response"
  {
    "message": "Thanks! Your submission has been received.",
    "redirect": "https://example.com/sales-thanks",
    "id": "01J...",
    "sandbox": false,
    "spam": null,
    "deliveries": null
  }
  ```

  `redirect` is the form's own `redirect_url` when no rule sets one, and `null` when neither is set.

A `_redirect` field is still honoured when its host is trusted. The rule's redirect host counts as trusted, along with the form's allowed origins. See [redirects](https://docs.getquickforms.com/submit/#redirects).

## Testing rules

Send a [sandbox](https://docs.getquickforms.com/sandbox/) submission. Its JSON response lists the deliveries that would have been sent, with each target, so you can check which addresses a set of answers reaches without sending anything.

Source: https://docs.getquickforms.com/routing-rules/index.mdx
