Skip to main content

What is a Group?

A group is the core organizing unit in Lit Chipotle. It binds together three things:
  1. Wallets (PKPs) — which wallets can be used
  2. IPFS Actions — which lit-actions can be executed
  3. Usage API Keys — which keys have access (via their permission arrays)
Think of a group as an access-control boundary: scoped usage keys can run actions in their permitted groups, and PKP wallet access requires a group permitting both the action and wallet. Wildcard execution keys can run arbitrary code without a group, but still need that group match to use a PKP wallet.
In this example, Key A can only use Group 1’s wallets and actions. Key B can use both groups. The account key administers all groups; use a usage key to execute actions.

Why Groups Exist

Without groups, every usage key would have access to every wallet and every action in your account. Groups let you:
  • Scope a key to a single dApp — give your price-oracle service a key that can only execute the price-oracle action using a specific wallet.
  • Isolate environments — separate staging actions from production actions.
  • Rotate access safely — revoke a usage key without affecting other keys or groups.

How Groups Connect to Everything

Common Patterns

One group per dApp

Give each dApp its own usage key scoped to its group. If the price-oracle key leaks, the minter is unaffected.

All-access key for development

Create a usage key with execute_in_groups: [0] (wildcard). This key can run arbitrary action code, including code pasted into the Dashboard Action Runner, without registering a CID or creating a group. Execution permission and PKP wallet permission are separate. If the action requests a PKP private key or uses PKP encryption/decryption, a group in the key’s own account must permit both the action CID and the requested wallet. They must match the same group. Wildcard execution skips the individual group grants on the key; it does not skip this resource check or grant access to another account’s wallets. Group membership is not proof of wallet ownership: listing a foreign wallet address can satisfy the group check, but the node separately resolves the wallet in the caller’s account and verifies the derived key’s address before releasing or using it. For example, console.log("hello") needs no group with a wildcard key. An action using wallet A requires a group containing wallet A and that action’s CID (or the group’s all-actions wildcard). Changing the code changes its CID, so update the permitted CID or deliberately allow all actions for that group. Use a scoped key when you want to restrict which code can execute. Expired and revoked keys do not gain access through wildcard permissions.

Delegating group management

The group-management permissions on a usage key (add_pkp_to_groups, remove_pkp_from_groups, manage_ipfs_ids_in_groups) are scoped by group, not by wallet or action. Treat a key holding them as an administrator of those groups:
  • add_pkp_to_groups: [g] lets the key add any wallet in the account to group g, including wallets that were never in g and the all-wallets wildcard (zero address), which also covers wallets created later. There is no per-wallet grant on a usage key.
  • manage_ipfs_ids_in_groups: [g] lets the key add any action CID to g, including the all-actions wildcard 0.
  • Any key with execute_in_groups containing g (including a wildcard execution key) can then use those wallets with those actions, which includes signing, decryption and getPrivateKey.
So add rights on g combined with execute rights in g, whether held by one key or by two, give effective access to every wallet in the account. This is by design. If some wallets must stay out of a delegate’s reach, keep them in a separate account, or keep wallet membership changes on the account key and give delegates only execute_in_groups.

Shared wallets across groups

A single wallet can belong to multiple groups. This is useful when multiple dApps need to sign with the same address but run different actions.

Group Lifecycle

  1. Create — POST /core/v1/add_group with a name and optional pre-permitted PKPs and CID hashes.
  2. Configure — Add wallets (add_pkp_to_group) and actions (add_action_to_group).
  3. Grant access — Create or update usage keys with the group ID in their permission arrays.
  4. Update — POST /core/v1/update_group to change name, description, or permission lists.
  5. Delete — POST /core/v1/remove_group to remove the group. Usage keys that referenced it lose that access.

Revocation during a running action

Each PKP private-key request and PKP AES encrypt/decrypt operation checks wallet permission through the shared blockchain cache, including repeated operations in the same action execution. An execution does not retain its first permission decision for its entire lifetime. Revocation is not instantaneous. API mutation hooks and the on-chain account-event listener selectively invalidate affected cache entries; the listener polls every 10 seconds. Cached grants expire after 300 seconds without a hit; each hit renews that window. Cached denials expire 30 seconds after insertion or update, without extension on reads. Both grants and denials are invalidated by relevant events: once a grant event is processed successfully, the next lookup can observe the new permission without waiting for the denial TTL. This is not instantaneous; mining, polling, RPC visibility, and usage-key invalidation affect propagation. There is no hard maximum age for a continuously used grant. If the listener misses an event or invalidation is incomplete, a hot stale grant can remain usable indefinitely. Denials retain their short TTL as a fallback. Once a fresh lookup is required, lookup errors stop the operation rather than falling back to an old grant. Wallet-derivation caching retains its separate fixed five-minute TTL. An operation whose permission check started before invalidation may still finish. Revocation does not erase a private key already returned to action code, terminate the running action, or revoke access granted through another matching group.

Permission Flags on Groups

When creating a group, two convenience flags control default access:
  • All wallets permitted — any wallet in the account can be used via this group (no need to add individually).
  • All actions permitted — any action CID matches this group, including code that has not been registered.
These are set in the Dashboard’s group creation form or via the pkp_ids_permitted and cid_hashes_permitted arrays in the API. On-chain, these flags are not separate booleans: they are encoded using wildcard values in the arrays:
  • To permit all wallets, include the zero PKP ID in pkp_ids_permitted:
    • pkp_ids_permitted: ["0x0000000000000000000000000000000000000000000000000000000000000000"]
  • To permit all actions, include 0 in cid_hashes_permitted:
    • cid_hashes_permitted: [0]
Leaving these arrays empty or omitting them does not mean “all” — it means no wallets/actions are automatically permitted by default.

Further Reading