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

# Validating Transactions

> Validate unsigned transactions against prior simulations before signing.

export const date_0 = "2026-04-07"

The validate endpoint ensures that the unsigned transaction you're about to sign matches exactly what was simulated. Each field is checked independently, so you know precisely what changed if validation fails.

```
POST https://shield.api.enso.build/api/v1/validate
```

## Request Parameters

| Field                 | Type            | Required | Description                                      |
| --------------------- | --------------- | -------- | ------------------------------------------------ |
| `simulationId`        | `string` (UUID) | Yes      | The `simulationId` from a prior `/simulate` call |
| `transaction.data`    | `string`        | Yes      | Hex-encoded calldata                             |
| `transaction.to`      | `string`        | Yes      | Target contract address                          |
| `transaction.from`    | `string`        | Yes      | Sender address                                   |
| `transaction.value`   | `string`        | Yes      | Native token value in wei                        |
| `transaction.chainId` | `number`        | Yes      | Chain ID                                         |

## Response

| Field            | Type      | Description                          |
| ---------------- | --------- | ------------------------------------ |
| `valid`          | `boolean` | `true` only when **all** checks pass |
| `simulationId`   | `string`  | The simulation ID validated against  |
| `checks.chainId` | `boolean` | Chain ID matches                     |
| `checks.data`    | `boolean` | Calldata hash matches                |
| `checks.to`      | `boolean` | Target contract address matches      |
| `checks.from`    | `boolean` | Sender address matches               |
| `checks.value`   | `boolean` | Native token value matches           |

## Examples

### Successful Validation

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://shield.api.enso.build/api/v1/validate \
    -H "Authorization: Bearer $ENSO_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "simulationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "transaction": {
        "data": "0x3593564c...",
        "to": "0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E",
        "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
        "value": "1000000000000000000",
        "chainId": 1
      }
    }'
  ```

  ```typescript TypeScript theme={null}
  const result = await fetch("https://shield.api.enso.build/api/v1/validate", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${ENSO_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      simulationId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      transaction: {
        data: "0x3593564c...",
        to: "0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E",
        from: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
        value: "1000000000000000000",
        chainId: 1,
      },
    }),
  }).then((res) => res.json());
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "valid": true,
  "simulationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "checks": {
    "chainId": true,
    "data": true,
    "to": true,
    "value": true,
    "from": true
  }
}
```

### Failed Validation (Tampered Data)

If the calldata has been modified since simulation, the `data` check will fail:

```json theme={null}
{
  "valid": false,
  "simulationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "checks": {
    "chainId": true,
    "data": false,
    "to": true,
    "value": true,
    "from": true
  }
}
```

## Interpreting Failed Checks

| Check     | When `false`            | Likely Cause                                                                          |
| --------- | ----------------------- | ------------------------------------------------------------------------------------- |
| `data`    | Calldata was modified   | Transaction payload was tampered with, or a different function/arguments were encoded |
| `to`      | Target contract changed | The transaction is being sent to a different contract than simulated                  |
| `from`    | Sender changed          | A different account is submitting the transaction                                     |
| `value`   | ETH value changed       | The native token amount was modified                                                  |
| `chainId` | Wrong chain             | The transaction is targeting a different chain than simulated                         |

<Warning>
  If any check fails, **do not sign the transaction**. Re-simulate to get a fresh `simulationId`, or investigate why the transaction changed.
</Warning>

## Cache Expiry

Simulations are cached for **5 minutes**. If you call `/validate` after the simulation has expired, you'll receive a `404` error:

```json theme={null}
{
  "statusCode": 404,
  "message": "Simulation a1b2c3d4-e5f6-7890-abcd-ef1234567890 not found or expired"
}
```

Re-simulate to get a fresh `simulationId` and try again.

## Best Practices

* **Validate immediately before signing** — Don't validate far in advance. Validate as close to the signing moment as possible within the 5-minute window.
* **Log the simulationId** — Store simulation IDs for debugging and audit trails.
* **Re-simulate on failure** — If validation fails, re-simulate to get a fresh result rather than retrying the same validation.
* **Check individual fields** — When `valid` is `false`, inspect the `checks` object to understand exactly what changed.

```typescript theme={null}
async function safeSign(simulationId: string, tx: UnsignedTransaction) {
  const validation = await validate(simulationId, tx);

  if (!validation.valid) {
    const failedChecks = Object.entries(validation.checks)
      .filter(([, passed]) => !passed)
      .map(([field]) => field);

    throw new Error(`Validation failed for: ${failedChecks.join(", ")}`);
  }

  return await wallet.sendTransaction(tx);
}
```

<div className="text-right text-xs gray-200 font-semibold w-full" style={{marginTop: '0'}}>
  <p style={{
        color: "#b2b2b2"  
    }}>Updated {date_0}</p>
</div>
