# Response template

Documentation owner: product `control`; documentation version: `next`.
Source: `content/products/control/next/modules/api/response-template.md` at commit `eaf7a020437971baeee95e87eaf963636040ac71`.

When the `Pipes` response handler is configured, you can control the response body using template properties:

- `response.template` — rendered when the pipe succeeds
- `response.failure_template` — rendered when the pipe fails and no per-reason template matches
- `response.status[].template` — per-reason template on a status entry; takes priority over `response.failure_template` when the entry matches

All templates use the same Mustache syntax and the same set of available scopes. If no template is set for a given outcome, the behavior differs: without `response.template` the raw pipe response JSON is returned; without any failure template the response body is empty.

## Syntax

Templates use [Mustache](https://mustache.github.io/) syntax.

| Expression | Description |
| --- | --- |
| `{{variable}}` | HTML-escaped value |
| `{{{variable}}}` | Raw (unescaped) value |
| `{{#section}}...{{/section}}` | Conditional or iteration block |
| `{{^section}}...{{/section}}` | Inverted block — renders when value is false or empty |

## Available scopes

Three scopes are available when the template is expanded.

### `response`

The full pipe response object. Use triple braces to embed the complete JSON without HTML escaping:

```
{{{response}}}
```

Individual fields are also accessible:

| Expression | Description |
| --- | --- |
| `{{response.success}}` | `true` if the pipe completed successfully |
| `{{response.reason}}` | Error reason when the pipe returns a failure |

### `items`

The list of items returned by the pipe. Access by index or iterate with `{{#items}}`.

**Direct access:**

| Expression | Description |
| --- | --- |
| `{{items.size}}` | Number of items |
| `{{items.N.id}}` | ID of item at index N |
| `{{items.N.size}}` | Number of properties on the item |
| `{{items.N.@index}}` | Zero-based index of the item |
| `{{items.N.@first}}` | `true` for the first item |
| `{{items.N.@last}}` | `true` for the last item |
| `{{items.N.<property>}}` | First value of a named property |
| `{{items.N.<property>.M.value}}` | Property value at index M |
| `{{items.N.<property>.M.@index}}` | Index of the property value |

**Iteration:**

Use `{{#items}}...{{/items}}` to loop over all items. Inside the block, properties are accessed by name directly. Use `{{#<property>}}...{{/property}}` to iterate over a multi-value property.

| Expression | Available inside `{{#items}}` |
| --- | --- |
| `{{id}}` | Item ID |
| `{{size}}` | Number of properties |
| `{{@index}}` | Zero-based item index |
| `{{@first}}` | `true` for the first item |
| `{{@last}}` | `true` for the last item |
| `{{<property>.N.value}}` | Nth value of a property |
| `{{.}}` | Current value when iterating a property list |

### `now`

| Expression | Description |
| --- | --- |
| `{{now}}` | Current timestamp as a formatted string |

## Success template example

```json
{
  "count": {{items.size}},
  "timestamp": "{{now}}",
  "users": [
    {{#items}}
    {
      "id": "{{id}}",
      "index": {{@index}},
      "displayName": [
        {{#displayName}}
        {"ix": {{@index}}, "value": "{{.}}"}{{^@last}},{{/@last}}
        {{/displayName}}
      ]
    }{{^@last}},{{/@last}}
    {{/items}}
  ],
  "raw": {{{response}}}
}
```

## Failure template

`response.failure_template` is rendered when the pipe fails for any reason — both logical failures (`PipeFailureException`, e.g. `FlowFail`) and infrastructure errors (e.g. LDAP, JDBC, or other valves that throw an exception). It uses the same Mustache syntax as `response.template`. The scopes `response`, `items`, and `now` are all available, but their values reflect the failure state:

| Scope | Value in a failure template |
| --- | --- |
| `{{response.success}}` | `false` |
| `{{response.reason}}` | The failure reason; for logical failures this is the pipe reason string, for infrastructure errors it is the exception message |
| `{{items}}` | Empty list |
| `{{now}}` | Current timestamp |

The HTTP status is determined by `response.status` mappings evaluated against `{{response.reason}}`. If no mapping matches, the status falls back to `400`.

The template used to render the failure body is chosen in this order:

1. The `template` field on the first matching `response.status` entry, if present.
2. `response.failure_template`, if configured.
3. Empty body otherwise.

### Failure template example

```json
{
  "failure_template": "{\"error\":\"{{response.reason}}\"}"
}
```

Produces `{"error":"NOT_FOUND"}` when the pipe fails with reason `NOT_FOUND`.

### Reproducing the legacy response format

Before `response.failure_template` was introduced, a pipe failure always returned a JSON body in the format `{"success":false,"reason":"...","data":{}}`. If a calling system depends on that format, configure a `failure_template` that reproduces it:

```json
"failure_template": "{\"success\":false,\"reason\":\"{{response.reason}}\",\"data\":{}}"
```

## Failure handling summary

| Situation | Body | HTTP status |
| --- | --- | --- |
| Pipe succeeds, `template` set | Rendered template | 200 |
| Pipe succeeds, no `template` | Raw pipe response JSON | 200 |
| `PipeFailureException` (e.g. FlowFail), `failure_template` set | Rendered failure template | Mapped status (default: 400) |
| `PipeFailureException`, no `failure_template` | Empty | Mapped status (default: 400) |
| Infrastructure error (LDAP, JDBC, …), `failure_template` set | Rendered failure template; reason = exception message | Mapped status (default: 400) |
| Infrastructure error, no `failure_template` | Empty | Mapped status (default: 400) |
| Template expansion error | Empty | 500 |
| Any other (non-pipe) exception | Empty | 500 |
