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

# Proxy Response Shaping

> Mutate the upstream response — status code, headers, or body — before GoDizzy returns it to your agent, without changing agent code.

When a routing rule is set to **Proxy**, GoDizzy forwards the request to your collection's target endpoint and streams the response back. By default the response is passed through unchanged. **Proxy response shaping** lets you intercept that response and modify it — changing the status code, injecting or removing headers, or transforming the body — before the caller receives it.

This is useful for injecting error codes that the upstream never returns in staging, normalizing inconsistent API shapes across environments, or testing how your agent handles missing or malformed fields from a live upstream.

## How shaping works

Shaping is an optional configuration attached to a proxy rule. When GoDizzy receives the upstream response it applies your shaping config in this order:

1. Override the status code (if configured)
2. Set or remove response headers
3. Transform the body

The shaped response is then returned to your agent or client.

<Note>
  Shaping configs are versioned the same way mock responses are — every save creates a new version, and you can view history and revert to any prior version.
</Note>

## Override the status code

Enter a replacement HTTP status code in the **Status code override** field. GoDizzy discards the upstream status and returns yours instead. Leave the field empty to pass the upstream status through unchanged.

**Example use case:** Your staging upstream always returns `200` for payment endpoints because the test environment never fails. Override to `402` to test how your agent handles a payment-required response without changing the upstream.

## Set and remove headers

In the **Headers** section of your shaping config, you can add header operations:

* **Set** — Adds the header to the response (or replaces it if the upstream already sent it). Provide a `set` object mapping header names to values.
* **Remove** — Strips the named header from the upstream response before returning it. Provide a `remove` array of header names.

You can combine both in the same config:

```json theme={null}
{
  "set": {
    "X-Upstream-Region": "us-east-1",
    "Cache-Control": "no-store"
  },
  "remove": [
    "X-Internal-Trace-Id",
    "X-Debug-Info"
  ]
}
```

Template variables (including `{{$reqBody['key']}}` and `{{$resBody['key']}}`) work in header values — see [Template variables](#template-variables) below.

## Transform the body

<Tabs>
  <Tab title="Unchanged (pass-through)">
    The default. GoDizzy returns the upstream body exactly as received. Select this mode when you only need to modify the status code or headers.

    ```json theme={null}
    {
      "mode": "unchanged"
    }
    ```
  </Tab>

  <Tab title="Full replace">
    Replace the entire upstream body with a body you provide. GoDizzy discards the upstream body and returns your configured payload instead.

    **When to use it:** The upstream returns a large or complex object and you want to substitute a minimal, controlled shape for testing.

    ```json theme={null}
    {
      "mode": "replace",
      "content": "{\"id\": \"{{$randomUUID}}\", \"status\": \"fulfilled\", \"amount\": {{$resBody['amount']}}, \"currency\": \"usd\", \"processed_at\": \"{{$isoTimestamp}}\"}"
    }
    ```

    The `content` field is a JSON string. Use `{{$resBody['key']}}` to pull fields from the upstream response into your replacement body.

    <Warning>
      Full replace discards the entire upstream body. If you only need to add or change specific fields, use **JSON field patch** instead.
    </Warning>
  </Tab>

  <Tab title="JSON field patch">
    Surgically set or remove individual top-level keys on the upstream JSON object. The rest of the upstream body is returned unchanged.

    Use this when the upstream response is mostly correct but you need to inject a missing field, change a specific value, or strip a field your agent should not see.

    Provide a `set` object (field names to values) and/or a `remove` array (field names to delete):

    ```json theme={null}
    {
      "mode": "jsonFields",
      "set": {
        "subscription_status": "past_due"
      },
      "remove": ["debug_info", "internal_trace"]
    }
    ```

    **Example — patch an upstream search response to simulate a missing field:**

    Upstream returns:

    ```json theme={null}
    {
      "results": ["..."],
      "total": 42,
      "next_cursor": "abc123",
      "debug": { "query_plan": "..." }
    }
    ```

    Patch config (remove `next_cursor` and `debug`, override `total` to 0):

    ```json theme={null}
    {
      "mode": "jsonFields",
      "set": {
        "total": 0
      },
      "remove": ["next_cursor", "debug"]
    }
    ```

    Shaped response returned to your agent:

    ```json theme={null}
    {
      "results": ["..."],
      "total": 0
    }
    ```
  </Tab>
</Tabs>

## Template variables

Proxy response shaping supports the same template variables as mock responses, plus one additional context: the upstream response body.

| Syntax                       | Available in  | Description                                          |
| ---------------------------- | ------------- | ---------------------------------------------------- |
| `{{$randomUUID}}`            | Body, headers | New UUID per response                                |
| `{{$isoTimestamp}}`          | Body, headers | UTC timestamp at response time                       |
| `{{$unixSeconds}}`           | Body, headers | Unix epoch seconds                                   |
| `{{$unixMs}}`                | Body, headers | Unix epoch milliseconds                              |
| `{{$date}}`                  | Body, headers | `YYYY-MM-DD` in UTC                                  |
| `{{$randomInt(a,b)}}`        | Body, headers | Random integer in range                              |
| `{{$randomAlphaNumeric(n)}}` | Body, headers | Random alphanumeric string                           |
| `{{$randomBoolean}}`         | Body, headers | `true` or `false`                                    |
| `{{$randomHex(n)}}`          | Body, headers | Random hex string                                    |
| `{{$reqBody['key']}}`        | Body only     | Top-level field from the incoming request JSON body  |
| `{{$resBody['key']}}`        | Body only     | Top-level field from the upstream response JSON body |

<Note>
  `{{$reqBody['key']}}` is only available when the rule's method is `POST`, `PUT`, or `PATCH`. `{{$resBody['key']}}` is only available in **Full replace** and **JSON field patch** body transforms — not in headers.
</Note>

## Version history and rollback

Every time you save a proxy shaping config, GoDizzy stores a new immutable version — identical to how mock response versioning works.

<Steps>
  <Step title="Open version history">
    On the rule detail page, click **View History** on the proxy shaping section. You will see a list of every saved config with the timestamp and the email of the team member who saved it.
  </Step>

  <Step title="Inspect a version">
    Click any version to see the full config: status override, header operations, and body transform mode and payload.
  </Step>

  <Step title="Revert">
    Click **Revert to this version**. GoDizzy creates a new version with the content of the selected config. Your full history is preserved.
  </Step>
</Steps>

## Example: normalize an inconsistent upstream

Your staging upstream returns a `user` object, but your production upstream wraps it in a `data` envelope. Use a full replace shaping config on the staging proxy rule to make staging return the same shape as production:

```json theme={null}
{
  "mode": "replace",
  "content": "{\"data\": {\"id\": {{$resBody['id']}}, \"email\": {{$resBody['email']}}, \"plan\": {{$resBody['plan']}}, \"created_at\": \"{{$isoTimestamp}}\"}}"
}
```

Your agent always sees `data.id`, `data.email`, and `data.plan` — regardless of which environment is serving the request.
