> ## 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.

# Permissions

> Control what transactions your server wallets can sign

Permissions let you define guardrails on your REST API wallets. Set up a policy through the [Para dashboard](https://developer.getpara.com) that specifies what transactions are allowed, and Para enforces it on every signing request. If a transaction violates the policy, the request is denied before anything is signed.

<Info>
  Permissions are **opt-in**. If you don't create a policy, all signing requests are allowed (existing behavior). Once a policy is active, it becomes **deny-by-default** — transactions must match an ALLOW rule.
</Info>

## Key Concepts

* **One active policy per API key.** Each policy contains one or more scopes, and each scope contains permission rules.
* **Deny-by-default.** When a policy exists, any transaction that doesn't match an ALLOW rule is denied.
* **DENY always wins.** If a transaction matches both an ALLOW and a DENY rule, it's denied.
* **Windowed spend limits.** Direct native transfers and direct ERC-20 transfers can be limited by cumulative amount per fixed time window.
* **EVM only.** Permissions currently evaluate EVM transactions. Solana and Cosmos are not yet supported.

## How Enforcement Works

When you call any signing endpoint (`sign-raw`, `sign-message`, `sign-typed-data`, `sign-transaction`, `transfer`), Para checks whether a policy exists for your API key. If one does, the transaction is evaluated against every scope and permission in the policy.

If the transaction is denied, you get a `403` response with details about which rule blocked it:

```json theme={null}
{
  "code": "POLICY_DENIED",
  "message": "Transaction denied by policy",
  "deniedBy": {
    "scopeName": "Token Transfers",
    "permissionType": "TRANSFER",
    "condition": {
      "resource": "TO_ADDRESS",
      "comparator": "CONTAINED_IN",
      "reference": ["0xabc...", "0xdef..."]
    }
  }
}
```

The `deniedBy` field tells you exactly which scope, permission type, and condition caused the denial, making it straightforward to debug.

Windowed spend denials use the same `403` `POLICY_DENIED` response. Para denies the request before signing, so no transaction is broadcast and no pending user review is created for REST API wallets.

## Permission Types

Each permission targets a specific kind of signing operation:

| Type              | Applies To                                                  |
| ----------------- | ----------------------------------------------------------- |
| `SIGN_MESSAGE`    | `sign-message`, `sign-typed-data`, and `sign-raw` endpoints |
| `TRANSFER`        | `transfer` endpoint (native token sends)                    |
| `CALL_CONTRACT`   | `sign-transaction` when calling a contract function         |
| `DEPLOY_CONTRACT` | `sign-transaction` when deploying a contract                |

## Condition Reference

Conditions narrow when a permission applies. Every condition has a **resource** (what to check), a **comparator** (how to check), and a **reference** (expected value).

### Resources

| Resource     | Description                                        | Used With                   |
| ------------ | -------------------------------------------------- | --------------------------- |
| `VALUE`      | Transaction value in wei                           | `TRANSFER`, `CALL_CONTRACT` |
| `TO_ADDRESS` | Destination address                                | `TRANSFER`, `CALL_CONTRACT` |
| `MESSAGE`    | The message being signed                           | `SIGN_MESSAGE`              |
| `ARGUMENTS`  | Contract function arguments (e.g., `ARGUMENTS[0]`) | `CALL_CONTRACT`             |

### Comparators

| Comparator         | Description                          | Reference Type      |
| ------------------ | ------------------------------------ | ------------------- |
| `EQUALS`           | Exact match                          | Single value        |
| `NOT_EQUALS`       | Must not match                       | Single value        |
| `GREATER_THAN`     | Numeric greater than                 | Number string (wei) |
| `LESS_THAN`        | Numeric less than                    | Number string (wei) |
| `CONTAINED_IN`     | Must be one of the listed values     | Array of values     |
| `NOT_CONTAINED_IN` | Must not be any of the listed values | Array of values     |

### Windowed Spend Limits

Use a `WINDOWED_SPEND_LIMIT` condition when a REST API wallet should automatically sign only up to a cumulative amount in a fixed time window. The reference object must include:

| Field            | Description                                                                 |
| ---------------- | --------------------------------------------------------------------------- |
| `assetType`      | `NATIVE` for native token transfers, or `ERC20` for direct ERC-20 transfers |
| `tokenAddress`   | ERC-20 token contract address. Required for `ERC20`, omitted for `NATIVE`   |
| `limitBaseUnits` | Maximum amount in the asset's smallest unit, as a decimal string            |
| `windowMs`       | Fixed window length in milliseconds                                         |

Windowed spend limits count transaction value only. They do not include gas or fees, and each limit is scoped by API key, wallet, chain, asset, and window length.

## Limitations

* **EVM only.** Solana and Cosmos transactions are not evaluated against policies.
* **Direct transfers only.** Windowed spend limits cover native transfers and ERC-20 `transfer(address,uint256)`. They do not cover approvals, `transferFrom`, router calls, multicalls, non-transfer contract calls, USD-normalized limits, or cross-asset aggregate limits.
