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

# Routing Forms Overview

> Build and read routing forms and their submissions through the Zeeg API, and map every answer into your own CRM.

A routing form asks an invitee a few questions and then sends that invitee to the right destination — a scheduling page, a team page, an external address, or a message. The Routing Forms API builds a routing form, reads its definition, and reads and deletes the submissions that invitees send through it.

## Scopes

| Scope                 | What it allows                                                                       |
| --------------------- | ------------------------------------------------------------------------------------ |
| `routing_forms:read`  | Read routing forms and their submissions                                             |
| `routing_forms:write` | Create, change and delete routing forms; delete submissions; also grants read access |

Every read endpoint accepts either scope. Every write endpoint requires `routing_forms:write`.

## Build a routing form

A routing form is built in three calls, because the questions and the routes replace as whole lists:

1. [Create a Routing Form](/api/routing-forms/create-a-routing-form) writes the routing form with its name and its page settings. The new routing form holds no question and one fallback route that shows the default thank-you page.
2. [Replace Routing Form Questions](/api/routing-forms/replace-routing-form-questions) writes the questions. The response carries the id of each question.
3. [Replace Routing Form Routes](/api/routing-forms/replace-routing-form-routes) writes the routes. A rule names its question by that id, in the `inputId` field.

[Update a Routing Form](/api/routing-forms/update-a-routing-form) changes the settings afterwards. It is a partial update: a field that the body leaves out keeps its stored value.

<Warning>
  The two `PUT` endpoints replace the whole list. A question or a route that the body leaves out is deleted. Read the current list, change it, and send it back complete.
</Warning>

## The two resources

### Routing forms

`GET /routing-forms` returns one entry per routing form. `GET /routing-forms/{id}` adds two lists to that entry:

* `inputs` holds the questions. A question carries its `type`, its `options`, and the CRM attribute it maps onto.
* `routes` holds the routes. A route carries its destination and the `rules` that select it. Exactly one route of a routing form is the fallback, which takes every submission that matches no other route.

A condition of a rule names its question with `inputId` on both surfaces. The read endpoints return that key and the write endpoints accept it.

### Submissions

The submissions of every routing form sit in one feed. `GET /routing-form-submissions` returns that feed, and `routingFormId` narrows it to one routing form. Filter further by creation time with `minCreatedAt` and `maxCreatedAt`, and by destination with `routeType`.

## Read the answers

Each answer ships twice, and the two values serve different consumers:

| Field       | What it holds     | Use it for              |
| ----------- | ----------------- | ----------------------- |
| `answer`    | The display value | Anything a person reads |
| `rawAnswer` | The stored value  | Mapping into a CRM      |

For a question that maps onto a CRM select attribute, `rawAnswer` is the canonical `{"id","value","color"}` JSON that identifies the option. The `id` in it is the value that your CRM needs. `answer` holds the label alone.

<Warning>
  Never show `rawAnswer` to a person. For a CRM select answer it is a JSON blob, not a label.
</Warning>

`questionsAndAnswers` repeats the same answers as a flat map from question text to display value. It matches the map that the `routing_form.submitted` webhook ships, so one parser reads both surfaces.

## Identifiers

Every id in this API is a UUID.

<Note>
  A malformed id answers `404`, not `422`. An id that names a resource outside your workspace answers `404` as well, so the response never tells you that the resource exists.
</Note>

## Timestamps

Every timestamp in a response is in **ISO 8601** format with a UTC offset, for example `2026-04-10T08:30:00+00:00`. The `minCreatedAt` and `maxCreatedAt` filters accept the same format.
