Author and test policies on a beta API key, shown as Development in the Developer Portal. Production keys are read-only. Once your beta policy is active, select Request production review in the Developer Portal, and Para reviews the policy and applies it to your production key.
Example
Each policy governs one wallet type and one ownership model. The Guardrail blocks large native transfers and token approvals from app-owned EVM wallets on Ethereum and Base. The Request lets an app pay two merchants up to 50 USDC a day from each user’s Base wallet, once the user consents.- Guardrail
- Request
treasury-limits.json
Document fields
Para rejects unknown keys at every level of the document, so a typo fails validation instead of being ignored.Para adds your account and app scope when it saves a policy. Leave
layer, partnerId and appId out of the JSON you submit, even when a policy you read back from Para includes them.Metadata
metadata.productMode sets the ownership model, which decides the wallets a policy can govern and the effects its rules can use.
Versions
A policyid has a series of immutable versions. Para saves each change as a new version and keeps the old one.
- A new policy can use any non-empty
version, but only a policy with an integer version can be replaced, so start with"1". - A replacement must use the next integer after the highest version of that
id, and must keep the sameselectorandproductMode. To change either, create a policy with a newid. - Users consent to one exact version of a Request. Once a new version is active, its
allowrules apply to a user only after that user consents to it, and until then matching requests go to the user for review. See Requests. - Activation windows belong to the saved policy, not the JSON. Set them in the Developer Portal or with the CLI’s
--effective-fromand--effective-untilflags.
Selector
The selector decides which signing requests the policy governs. Every field you include must match the request, and a field you leave out matches everything. A list matches any of its entries.
A selector cannot name both
walletId and userId. Para also applies the ownership model itself: a Guardrail never governs a wallet with a user owner, and a Request never governs a wallet your account owns.
When you validate or save a policy, every listed wallet must exist, be governed by your account, support walletType and match the policy’s ownership model. Every listed user must own a wallet your account governs. Para rejects other values with selector_value_not_authorable.
Network identifiers
Write each network in a form the selector accepts for its wallet type. Para rejectsunscoped, raw-signing placeholders such as evm:raw, and networks of another wallet type.
A
chainId list does not pool anything across networks. Each network keeps its own spending budget; see Metered facts.
Requests without a network
Some signing requests carry no network. A request without a network matches only selectors that leave outchainId, so a policy that sets chainId never governs it.
Rules
A rule names the actions it governs, one condition, and the effect that applies when the condition matches.Effects by mode
The policy mode limits the effects a rule can use. Para checks this when you validate or save the policy.Actions
Para assigns every signing request one or more actions, and a rule applies only to the actions it names. Each wallet type supports a fixed set.
When you sign EIP-712 typed data through the viem v2 or ethers v6 integration or the wagmi connector, the Para SDK sends the typed data with its hash. Para checks that the two match and evaluates the request as
sign_typed_data, the same as the REST API’s sign-typed-data route, so request.typedData.primaryType, request.approvalLike and the chain ID from the typed data’s domain apply. Para evaluates these SDK requests as sign_message, with no chain ID: EIP-7702 authorizations, typed data signed through the viem v1 or ethers v5 integration, and a typed data hash that your code signs with signMessage. The sign_authorization action and its facts apply only to the REST API’s sign-authorization route, which the REST SDK calls.
For execute_safe_transaction, Safe SafeTx messages and Safe 4337 SafeOp messages, the request.safe.* facts describe the payment the Safe makes. See Safe payments. For execute_safe_transaction, SafeTx messages and readable SafeOp messages, they also describe a contract call that the Safe makes, when Para reads the call with a verified ABI. See Safe contract calls.
Every fact a rule reads must be available for every action the rule names, or validation fails with fact_action_unsupported. Facts and conditions lists the actions for each fact.
"actions": "all" covers every action of the wallet type, raw_signature included, but the validation fact check leaves raw_signature out. An "all" rule can therefore read only request.classification, the para.wallet.* facts and, on Solana, Cosmos, Stellar and Sui, request.actionFamilies. A raw signature has no request.actionFamilies, so a condition on it is indeterminate on a raw signature unless another condition in its group settles it, and Para then denies the raw signature unless another matching rule has the same or a stronger effect. See Facts Para cannot read.
On Solana, Cosmos, Stellar and Sui, "all" also covers transaction parts Para cannot classify, which no action list can name. Sui token transfers fall in this group because Sui has no transfer_tokens action.
How Para assigns actions to a request
How Para assigns actions to a request
A request with several actions is evaluated once per action, and the most restrictive result applies.
Conditional approval requirements
AnapprovalRequirement turns a require_approval rule into a structured workflow: ordered stages of eligible people who approve the request before Para signs it. The rule’s when still decides which requests need approval.
Conditions
A rule’swhen holds exactly one condition. Leaf conditions test facts about the request, and group conditions combine other conditions, so one rule can express AND, OR and NOT logic.
Facts and conditions covers each operator, value encoding and fact, and the size limits of a condition tree.
Condition outcomes
A leaf can also be indeterminate when the request does not provide the fact it reads, or not applicable when a metered fact does not apply to the request. Groups combine these outcomes as follows:
A rule whose condition is not matched or not applicable does not apply. An indeterminate rule can block the request; see Facts Para cannot read.
This rule allows native transfers of up to 0.01 ETH to either of two recipients:
User-adjustable amounts
A Request can let each user change an amount limit. Add aparameter to a compare or aggregate condition, and the condition’s value becomes the default. This condition caps each token transfer at 10 USDC unless the user sets another amount:
min and max to parameter as integer strings in base units. User-adjustable parameters lists the supported facts and operators, and how saved values interact with consent.
How Para decides
For each signing request, Para collects the active policies whose selector matches, evaluates their rules, and returns one decision: sign, deny, or wait for review or approval.Effect precedence
Every rule whoseactions include the request’s action is evaluated. Among the rules that match, the most restrictive effect wins:
denyrequire_approvalallow
allow rule never overrides a matching deny or require_approval. For example, a Request that allows small transfers and requires approval for one recipient still requires approval for a small transfer to that recipient.
When several matching rules share the winning effect, the first one in stack order wins. For require_approval, its approvalRequirement is the one that applies.
Multiple active policies
You can keep several active policies for each mode, and every one whose selector matches the request applies together. Validation reports active policies whose selectors overlap a new policy, but overlap is allowed. Para orders the stack by putting Para’s own policies first. Your policies follow, starting with the ones that set the fewest selector fields, then sorted byid, then by version compared as text. Stack order matters only for ties between rules with the same effect.
When no rule matches
When no rule decides a request, Para’s default for the wallet applies:
A Request’s
allow rules take effect only after the user consents to the policy. Until then, or when the user chose to review each request, matching requests also go to the user for review.
Facts Para cannot read
Some facts depend on what Para can decode from the request. A recipient, for example, exists only for a transfer Para recognizes. When a rule reads a fact the request does not provide, the rule’s condition is indeterminate. To scope a rule to requests it was written for:- Name only the actions the rule is about. Facts and conditions marks which facts are always present for an action and which depend on decoding.
- Add an always-present test to an
allgroup. When that test does not match, the group does not match, even if another child is indeterminate. notdoes not help: it leaves an indeterminate outcome unchanged.
deny rule for execute_safe_transaction and sign_typed_data with one of these conditions:
request.safe.innerDecodedeqfalsedenies every Safe transaction that Para does not read as a payment, including every contract call from the Safe.request.safe.callKindequnreaddenies the Safe transactions that Para reads neither as a payment nor as a contract call. Pair it with a rule that denies arequest.safe.callKindofcontract_callwhenrequest.safe.contract.addressorrequest.safe.abi.selectoris not on your list.
SafeTx or SafeOp message. See Safe payments and Safe contract calls.
Para still denies some requests before any rule runs, such as a malformed or invalid transaction, a Solana, Cosmos or Sui transaction that the signing wallet is not a required signer of, or a smart account operation that is not a managed ERC-20 transfer (unsupported-request). Contract calldata Para cannot decode is not malformed by itself; those requests follow the applicable rules and Para baseline.
Raw signatures
While Permissions is on, raw signatures follow the same defaults as other signing requests: an app-owned wallet signs them, and a user-owned wallet sends them to the user for review. Rules that name theraw_signature action, and rules with "actions": "all", can change that. Raw signatures are sign-raw requests, messages from Solana, Stellar and Sui wallets, and REST sign-message requests from a Cosmos wallet that do not pass walletType: "EVM". The SDKs sign messages from Cosmos wallets as EVM sign_message requests. Raw signatures carry no network a selector can name, so only a policy without chainId governs them. A rule that names raw_signature can read only para.wallet.* facts. The Developer Portal forms cannot create one, so write it in policy JSON, with Edit JSON in the Developer Portal or with the CLI.
Use a Guardrail deny or require_approval rule to stop or hold raw signatures from wallets that should not produce them, and select those wallets with walletId or a para.wallet.* condition.
To let users’ wallets sign raw signatures without a review each time, add this rule to a Request without chainId. It takes effect once the user consents, like any Request allow rule. Every rule needs a when, so the rule tests para.wallet.hasUserOwner, which is always true for the wallets a Request governs.
Validate a policy
Validate a policy before you save it. The Developer Portal JSON editor validates when you select Review, and the CLI validates withpara keys permissions validate --file policy.json. para keys permissions catalog --json prints the fact catalog for your key.
Each error has a code, a JSON path such as $.rules[0].when.fact, and a message. Schema problems without a more specific code, such as an unknown key or a malformed condition, return partner_policy_schema_invalid with a message naming the field.
Document and selector
Document and selector
Rules and effects
Rules and effects
Conditions and facts
Conditions and facts
Saving, replacing and activating
Saving, replacing and activating