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

# Validate Agreement Structure

> Check authored agreement JSON, read validation feedback, and distinguish template validation from deployment preflight.

For the complete documentation index, see [llms.txt](https://docs.shodai.network/llms.txt).

Validate authored agreement JSON with `client.validateTemplate(...)` before preparing deployment values, participant wallet mappings, signer data, or permits.

<Note>
  Structural validation checks authored agreement JSON only. [Deployment preflight](/workflow/deploy-an-agreement#preflight-the-deployment-request) checks the authored agreement plus deployment values, participant mappings, observers, and normalized variables.
</Note>

## When to validate

Run structural validation after authoring and before deployment preflight when:

1. participant roles are modeled
2. states and inputs reflect the intended workflow
3. `execution.initialize` is in place
4. you want feedback before assembling deployment context

At this point, the question is not "can I deploy?" The question is "does this agreement expose the participant roles, state IDs, and input IDs I expect?"

## Validate the authored agreement

<Tabs>
  <Tab title="SDK">
    ```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
    import { ApiClient } from '@cns-labs/agreements-api-client';

    const client = new ApiClient({
      baseUrl: process.env.BASE_URL!,
    apiKey: process.env.API_KEY,
    });

    const result = await client.validateTemplate(agreement);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    curl -sS "$BASE_URL/v0/agreements/validate-template" \
      -X POST \
      -H "Content-Type: application/json" \
    -H "X-API-Key: $API_KEY" \
      --data @agreement.json
    ```
  </Tab>
</Tabs>

The input is the authored agreement JSON itself. Do not wrap it in a deployment payload.

## Read the response

The raw HTTP response is wrapped in a `data` envelope with request metadata. `client.validateTemplate(...)` unwraps `data` and returns the validation summary directly.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "data": {
    "templateId": "did:template:service-retainer-manual-balance-v0-1",
    "participantVariableKeys": [
      "serviceProviderRepresentative",
      "clientRepresentative"
    ],
    "inputIds": [
      "submitInitialPaymentProof",
      "submitInvoice",
      "submitInvoiceWithTopup"
    ],
    "stateIds": [
      "AWAITING_PAYMENT",
      "WORK_IN_PROGRESS",
      "INVOICE_SUBMITTED"
    ],
    "warnings": []
  },
  "meta": {
    "apiVersion": "v0",
    "requestId": "req_123"
  }
}
```

| Field                     | How to use it                                                              |
| ------------------------- | -------------------------------------------------------------------------- |
| `templateId`              | Confirms the agreement metadata identity when one is present.              |
| `participantVariableKeys` | Confirms which participant-role variables the agreement exposes.           |
| `inputIds`                | Confirms which authored business events can be submitted later.            |
| `stateIds`                | Confirms which lifecycle states the agreement defines.                     |
| `warnings`                | Flags unusual or incomplete authoring choices to review before deployment. |

## What validation does not prove

Passing `POST /v0/agreements/validate-template` does not prove that:

1. deployment values are present
2. participant wallet addresses have been supplied
3. observers are valid for your deployment context
4. signer or permit data is ready
5. the agreement has been deployed
6. every future input will be valid from every live state

Use `POST /v0/agreements/validate` during [deployment](/workflow/deploy-an-agreement) to preflight the assembled deployment request. That deployment preflight does not deploy and does not validate permit signatures.

## Use the result as authoring feedback

If participant keys are missing, inspect participant variables and `subtype: "participant"`. If input IDs are missing, inspect `execution.inputs`. If state IDs are unexpected, inspect `execution.states` and transitions. If warnings appear, resolve or consciously accept them before signing deployment data.

## Next step

When participant keys, state IDs, input IDs, and warnings match your intent, continue to [Deploy an Agreement](/workflow/deploy-an-agreement).
