Skip to main content
The para keys permissions commands check a Guardrail or Request policy written as JSON against your API key and move it from draft to active to retired. The same commands run in a terminal or in a CI job.
You author and test policies on your beta API key. The CLI cannot change production policies: once a policy works on beta, you ask Para to review it and apply it to your production key.

Before you start

Every command acts on one API key in your selected organization and project, so set that context first.
1

Install the CLI and sign in

Install the CLI, then sign in with your developer account.
2

Select the organization and project

3

Find your beta key

Copy the key’s ID. The examples on this page call it KEY_ID. The Developer Portal shows this key as the Development key. If the project has a single beta key, you can leave KEY_ID out.
The CLI uses beta keys unless you changed its default. If PARA_ENVIRONMENT, a .pararc file, or defaultEnvironment selects prod, add --environment beta to the commands on this page.

Inspect the key

Read what the key already has before you change it. state returns every policy record on the key, and catalog returns the policy language the key accepts.
Without --json, state prints a summary: the state name, whether Permissions is enabled, and how many policies are active and in draft. The JSON lists every record in policies, plus activePolicies (active records whose time window is open now) and draftPolicies. Each record has these fields: catalog returns the condition kinds, effects, selector scopes, and facts the key accepts, with the operators each fact allows. Without --json, it prints only the catalog versions and the number of facts.

Write the policy

A policy file holds one JSON object. metadata.productMode sets its kind: "guardrail" for app-owned wallets, or "delegation" for a Request on user-owned wallets. Write amounts as strings in the chain’s base units, such as wei or lamports, and use integer strings for version, starting at "1", because replace expects the next integer.
This Guardrail limits SOL transfers from the app-owned Solana wallets on the key. It blocks any transfer above 2 SOL, and any transfer that would take a wallet past 10 SOL in one UTC day.
guardrail.json
A Guardrail rule can deny or require_approval. Without a walletId in the selector, the policy covers every app-owned Solana wallet on the key.Para also accepts a Guardrail allow whose only action is raw_signature, but a Guardrail never needs it: app-owned wallets already sign raw signatures by default. Raw signatures carry no network a selector can name, so a policy that sets chainId, like this one, never matches them. To deny raw signatures or require approval for them, write a Guardrail without chainId.

Validate, create, and activate

A new policy goes through three commands. It affects signing only after the last one.
1

Validate

validate checks the policy against the key without saving anything. It covers the schema, the rules allowed for the policy’s kind, the facts and actions available for its wallet type, and any wallets or users the selector names. An invalid policy prints each error with its JSON path and exits with code 10. A valid policy prints a warning for each active policy of the same kind whose selector overlaps it, because both policies can apply to the same requests.Two policy features must be enabled for the key before you use them: approval requirements (approvalRequirement on a rule) and adjustable parameters. If the policy uses one that is not enabled, validation fails with permissions_v2_extension_unavailable. Contact Para to enable it.
2

Create a draft

create validates the file again, saves it as a draft, and prints the new recordId with the activate command to run next. A draft does not affect signing. The key holds one Guardrail draft and one Request draft at a time, so activate or archive a draft before you create another of the same kind.
3

Activate

activate asks for confirmation, makes the draft active, and turns on Permissions for the key. It works only while the draft’s time window is open. If another version of the same policy id is active, that version becomes superseded. Activation can also invalidate open approval cases. Read state to confirm the result.
If the key still uses a policy from Para’s earlier permissions system, the first activation replaces it. That earlier policy does not come back if you later deactivate every policy.

Test on beta

A valid policy can still miss your intent. On beta, send at least one request that each rule should stop and one it should let through, using the same wallets and flows as your app. Exercise a Guardrail by signing from an app-owned wallet on your backend, and a Request by having a test user grant consent in your app first. Each platform’s guide covers the details: REST API, Node & Server, React & Web, and React Native.

Update a policy

replace publishes the next version of a policy from an edited file. Use it to change rules, conditions, or the time window of a draft or active policy.
The edited file keeps the id, selector, and metadata.productMode of the record it replaces, and sets version to one more than the highest version of that policy, for example "2" after "1". To cover different wallets or networks, create a separate policy instead. Without --effective-from or --effective-until, the new version keeps the current time window. To stage a change instead, create the next version as a draft and activate it when you are ready. Activation supersedes the active version with the same id. Replacing an active policy can invalidate open approval cases.
Users consent to one exact version of a Request. When you replace an active Request, each user has to consent again before the new version’s rules apply to them.

Deactivate and archive

Deactivate a policy to stop enforcing it, and archive records you no longer need. The Developer Portal calls these actions turning a permission off and deleting it.
deactivate moves an active record to inactive. An inactive record cannot be activated again, so to restore the policy, create it with the next version, activate that draft, and archive the old record. archive retires a draft, inactive, or superseded record; deactivate an active record before you archive it. Both commands ask for confirmation unless you pass --yes. deactivate can also invalidate open approval cases.
Permissions enforces policies for a key only while at least one active policy is inside its time window. When the last one is turned off or its window ends, Para stops checking policies on REST and SDK signing. App-owned wallets then sign without checks. User-owned wallets show the same review pop-ups as a key without Permissions, such as those the Transaction Pop-ups setting turns on.

Open approval cases

When a rule requires approval, the signing request opens an approval case and waits for reviewers. An approval case is open while it is pending, and after it completes until it is used to sign or expires. Para refuses a change that would invalidate open cases until you confirm it. A confirmed change ends those cases as invalidated, and their requests need a new attempt. In the CLI, replace, activate, and deactivate run this check: With --yes --json, the error looks like this:
Pass --force only when the requests behind those cases can be sent again under the new policies. create and archive never touch approval cases, so they have no --force flag.

Schedule with time windows

A time window limits when an active policy applies. Set it with --effective-from and --effective-until on create or replace; activate takes no window flags.
This draft’s window opens when create saves it, so you can activate it right away. The policy stops applying after 23:59:59 UTC on December 31, 2026. activate works only while the draft’s window is open. Before a later --effective-from arrives, activate exits with code 10 and reports policy_record_activation_window_inactive. To start a policy at a set time, create the draft in advance and run activate at or after its start, for example from a scheduled CI job. Until you activate or archive that draft, the key cannot hold another draft of the same kind.
  • Write timestamps in UTC as ISO 8601 ending in Z, with optional milliseconds, such as 2026-11-01T00:00:00.000Z. Offsets such as +01:00 are rejected.
  • --effective-until must be later than --effective-from. The window includes both ends.
  • Without --effective-from, create opens the window when it saves the draft. Without --effective-until, the window has no end.
  • On replace, each flag you leave out keeps the current record’s value.
An active policy past its effectiveUntil no longer applies, and the Developer Portal shows it as Expired. Because replace needs both windows open, you cannot replace an expired policy. Create the next version with a current window and activate it instead.

Run in CI and scripts

The commands run without prompts once they have everything they need. Pin the environment, organization, project, and key, pass --yes to the commands that ask for confirmation, and add --json to read results.
  • replace, activate, deactivate, and archive require --yes with --json.
  • --yes does not confirm changes that invalidate open approval cases. If replace, activate, or deactivate would invalidate them, the command makes no change and exits with code 10, with PERMISSIONS_V2_APPROVAL_CASES_AFFECTED in the --json output. Pass --force only in jobs that are meant to invalidate them.
  • Pass the key ID. With --json, the CLI cannot ask which key to use when the project has more than one beta key.
  • --file - reads the policy from a pipe. The CLI refuses stdin from an interactive terminal.
  • Every command uses the developer session that para login stores. para auth status fails early when that session is missing or expired.
Read the JSON on stdout and the exit code to decide what the job does next.
With --json, each command writes one JSON document to stdout.
The CLI never retries create, replace, activate, deactivate, or archive. If it cannot confirm that a change went through, it exits with PERMISSIONS_V2_WRITE_OUTCOME_UNKNOWN. Read state before you run the command again. activate, deactivate, and archive check state themselves and report success when the record already has its new lifecycle, and running create again with the same file returns the existing draft instead of saving a second one.
The Permissions errors reference lists the error codes these commands can return.

Go to production

The CLI writes only to beta keys. create, replace, activate, deactivate, and archive stop with PERMISSIONS_BETA_KEY_REQUIRED when the key is not a beta key, including with --environment prod. state, catalog, and validate work on any key, so you can read the policies on your production key from the CLI. Publishing to production goes through a review. Once your policies work on beta, request a production review from your Production key in the Developer Portal, and Para applies the reviewed policies to production. Follow Go to production for your platform: REST API, Node & Server, React & Web, or React Native.

Next steps

For every argument and flag, see the command reference.