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

# Author policies with JSON

> Validate, create, and activate advanced permissions policies on a beta API key

Learn how to publish a policy outside the Developer Portal forms. Use the CLI for supported wallet types, nested conditions, personal limits, or approval requirements that you want to author directly as JSON. Contact Para for help checking an advanced policy before relying on it.

<Steps titleSize="h2">
  <Step title="Authenticate and select the beta key" id="authenticate-and-select-the-beta-key">
    [Install the CLI](/v3/cli/installation), then authenticate with your developer account. These commands require access to the selected organization and project, not just possession of its public API key.

    ```bash theme={null}
    para login
    para orgs switch
    para projects switch
    para keys list --environment beta
    para keys permissions state KEY_ID --environment beta --json
    para keys permissions catalog KEY_ID --environment beta --json
    ```

    Use the key's ID for `KEY_ID`. The catalog describes the available authoring language; `state` returns the current policy records. Use `para keys permissions state` to manage these policies; the parent command returns a legacy status view.
  </Step>

  <Step title="Start with a Solana transfer Request" id="start-with-a-solana-transfer-request">
    Save this document as `solana-transfers.json`. It asks a user for standing access to native SOL transfers up to 0.01 SOL. `10000000` is an integer amount in lamports, not a dollar amount. The asset condition prevents another asset from being mistaken for native SOL.

    ```json solana-transfers.json theme={null}
    {
      "id": "solana-small-transfers",
      "schemaVersion": "permissions.policy.v1",
      "version": "1",
      "selector": {
        "walletType": "SOLANA",
        "requestRoute": "solana.sign_transaction",
        "requestType": "solana_transaction"
      },
      "rules": [
        {
          "id": "small-native-transfer",
          "effect": "allow",
          "when": {
            "kind": "all",
            "of": [
              { "kind": "compare", "fact": "request.classification", "op": "eq", "value": "native_transfer" },
              { "kind": "compare", "fact": "request.value.asset", "op": "eq", "value": "solana:native" },
              { "kind": "compare", "fact": "request.value.baseUnits", "op": "lte", "value": "10000000" }
            ]
          }
        }
      ],
      "metadata": {
        "productMode": "delegation",
        "description": "Send up to 0.01 SOL per native transfer"
      }
    }
    ```

    This selector applies to matching Solana signing requests under the selected API key. Add `walletId` to limit it to one wallet. For an app-owned wallet, design a Guardrail with the appropriate deny/approval rules instead of assuming this user-consent Request has the same meaning.
  </Step>

  <Step title="Validate, save, and activate" id="validate-save-and-activate">
    ```bash theme={null}
    para keys permissions validate KEY_ID --file solana-transfers.json --environment beta --json
    para keys permissions create KEY_ID --file solana-transfers.json --environment beta --json
    ```

    Inspect the validation result and returned draft. Copy the new `policy.recordId` from the create response, then activate that record:

    ```bash theme={null}
    para keys permissions activate RECORD_ID KEY_ID --environment beta --yes --json
    para keys permissions state KEY_ID --environment beta --json
    ```

    Validation checks the policy against the trusted project/key context. Creating a draft does not enable its behavior. Activation enables policy enforcement and supersedes an active version with the same logical policy ID.

    <Warning>
      The CLI accepts advanced JSON, but does not bypass policy validation, organization permissions, or the beta-only mutation boundary. A successful validation is not proof that the policy expresses your intent; test both matching and non-matching requests.
    </Warning>
  </Step>

  <Step title="Exercise the user flow" id="exercise-the-user-flow">
    Use the normal Solana signer integration with a user-owned wallet. Grant the Request through Portal, then test an amount below the limit and one above it. The first can use standing access; the second does not receive permission from this rule and follows the remaining policies and review flow.

    <Card title="Integrate consent and adjustable limits" icon="user-check" href="/v3/react/guides/permissions">
      Request consent before a transaction, inspect the result, and expose personal settings.
    </Card>
  </Step>
</Steps>

## Update or retire the policy

To replace a policy, keep its logical `id`, use its next version, and provide the new JSON. Replacing an active record takes effect immediately; replacing a draft keeps the replacement in draft.

```bash theme={null}
para keys permissions replace RECORD_ID KEY_ID --file solana-transfers-updated.json --environment beta --yes --json
para keys permissions deactivate ACTIVE_RECORD_ID KEY_ID --environment beta --yes --json
para keys permissions archive INACTIVE_RECORD_ID KEY_ID --environment beta --yes --json
```

Read the state again after each change. If a command cannot confirm whether a mutation completed, inspect the current records before retrying. Do not blindly create another version.

<CardGroup cols={2}>
  <Card title="Build more complex policies" icon="code" href="/v3/references/permissions/policy-json">
    Add nested logic, other wallet types, spending windows, adjustable values, and approval requirements.
  </Card>

  <Card title="Manage versions and production review" icon="rotate" href="/v3/general/permissions-lifecycle">
    Understand activation windows and the separate, Para-reviewed production publication process.
  </Card>
</CardGroup>
