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

# Overview

> With Turnkey you can create multi-user accounts with flexible co-ownership controls. This primitive enables you to establish delegated access to a user’s wallet, reducing or removing the need for them to manually approve each action. You can provide a smoother user experience while ensuring that end-users maintain full control over their wallets.

Delegated access works by creating a specialized business-controlled user within each end-user’s sub-organization that has carefully scoped permissions to perform only specific actions, such as signing transactions to designated addresses. This can enable your backend to do things like:

* Automate onchain actions such as staking, redemptions, or limit orders
* Sign transactions to whitelisted addresses without user involvement
* Perform scheduled operations (e.g. payouts, rebalances)
* Respond to specific onchain events programmatically

## Implementation flow

You can implement Delegated Access for an embedded wallet in two ways, depending on whether the setup runs from the frontend (recommended) or the backend.

### 1. Frontend (recommended)

This approach uses the **end-user’s authenticated session** to configure delegated access directly within their sub-organization. The flow is:

* Create an **API-only user (Delegated User)** with a P-256 API key authenticator that you control. This key can then be used server-side to sign transactions on the user’s behalf.
* Define **policies** for the Delegated User that strictly limit which transactions they are allowed to sign.

**Why this approach:**
This avoids temporarily granting the Delegated User root access — see [Caution](#caution) for more details. Since you’re using the client-side authenticated session, the API-only user is created directly as a **non-root** user within the sub-organization.

**Advantages:**

* There’s no possibility of elevated (root-level) access for the delegated user.

**Limitations:**

* You can’t assume the delegated user or its policies already exist. Before referencing it, you’ll need to call `fetchOrCreateP256ApiKeyUser` and `fetchOrCreatePolicies` to ensure the user and permissions are properly set up.

For a detailed step-by-step guide see [Client-side Delegated Access setup](/concepts/policies/delegated-access-frontend).

### 2. Backend

If you prefer to configure delegated access entirely server-side, the flow differs because the end-user in the embedded wallet model does not hold an API key. In this case, you must:

* Create the sub-organization with **two root users**: the end-user and your Delegated User (API key authenticator).
* Use the delegated access API key to add policies explicitly granting the DA user the limited actions you want them to perform.
* Update the root quorum so that only the end-user remains a root user.

<h4 id="caution">Caution ⚠️</h4>
When the delegated access setup is performed from the backend, your service (not the end-user) initiates and approves the sub-organization creation, delegated user addition, and root quorum updates.
This means the delegated user is temporarily added to the root quorum without direct end-user consent. If any of these operations fail — particularly the quorum update — the delegated user may unintentionally retain root privileges, effectively gaining unrestricted access to the user’s wallet.

If you adopt this approach, implement strict validation to confirm that:

* The root quorum was successfully updated; and
* The delegated user no longer retains unintended permissions once setup completes.

**Advantages:**

* Guarantees that the delegated user exists and can perform the required actions without additional setup.

**Limitations:**

* Risk of elevated access if the delegated user isn’t successfully removed as a root user, it may retain unintended control.
* Since all actions are service-initiated, there’s no explicit end-user approval in this flow.

For most end-user applications, it’s recommended to perform delegated access setup client-side, where all actions are explicitly initiated and approved by the user.

For a detailed step-by-step guide see [Server-side Delegated Access setup](/concepts/policies/delegated-access-backend).

## Frequently Asked Questions

### Policy design and creation

<Accordion title="Can I create policies on behalf of a user without their explicit approval?">
  Yes — if the delegated access (DA) user is part of the root quorum, they can create policies unilaterally. Once removed from the root quorum, only the remaining quorum member (typically the end-user) can make further policy changes.

  Note: This can also be done even if the initiating (delegated) user is not a root user, provided a policy explicitly grants them permission to create policies. However, such a configuration should be carefully scoped — additional restrictive policies are typically required to prevent the delegated user from granting themselves broader or unintended access.
</Accordion>

<Accordion title="When does the user 'approve' a delegated access setup?">
  When the delegated access setup is performed **client-side**, all actions are initiated and approved by the authenticated end-user within their session. This ensures full transparency and explicit user consent for every operation.

  <br />

  When performed **server-side**, the setup happens without direct user involvement. This approach is generally used only in **enterprise or custodial environments**, where your backend manages sub-organizations and delegated users on behalf of end-users.

  <br />

  For typical end-user applications, the client-side setup is the recommended and more secure approach.
</Accordion>

<Accordion title="After a limit order is filled, how can I remove/null a policy programmatically?">
  As long as the DA user remains authorized, they can remove policies programmatically. If they’ve been removed from the quorum, policy deletion will require the user’s explicit approval.

  **<u>NOTE:</u>** Turnkey is looking to support the concept of 'one-time-use policies' to make it easier to manage redundant policies.
</Accordion>

### Security and risk management

<Accordion title="If a delegated API key is leaked, does that allow someone to act on behalf of the user?">
  Yes — if the key is attached to a broad policy. That’s why it’s important to limit the scope of policies and enforce API hygiene practices.
  It's also recommended to have a policy in place that would allow this user to self-delete in case of a potential key leak:

  ```json theme={"system"}
  {
    policyName: `Allow the Delegated user to self-delete`,
    effect: "EFFECT_ALLOW",
    consensus: `approvers.any(user, user.id == '${delegated_userid}')`,
    condition: `activity.type == 'ACTIVITY_TYPE_DELETE_USERS' && activity.params.user_ids.count() == 1 && '${delegated_userid}' in activity.params.user_ids`,
    notes: "Allow the Delegated user to delete itself in case of a key leak"
  }
  ```
</Accordion>

<Accordion title="Is this the same risk as having a master delegate account?">
  In effect, yes. The key difference is that granular policies **can restrict** what a DA user can do, offering better security hygiene even if there's still elevated access.
</Accordion>

<Accordion title="What are best practices for storing and rotating Delegate Access API keys?">
  Typically this is a combination of, or all of the following practices, though not exclusive to just these:

  * Using short-lived keys whenever viable
  * Rotating API keys regularly
  * Monitoring the usage
  * Secure storage (e.g. in HSMs or vaults)
</Accordion>

### Best practices

<Accordion title="How do I scope a delegated access policy to reduce signing risk?">
  You can define strict transaction conditions. For example:

  ```javascript theme={"system"}
  solana.tx.instructions.count() == 1 &&
  solana.tx.transfers.count() == 1 &&
  solana.tx.transfers.all(transfer, transfer.to == '<SPECIFIC_ADDRESS>')
  ```

  You can also consider the following:

  * Recipient address restrictions (ie allowlisting addresses)
  * Contract method selectors
  * Transaction structure invariants
  * Blockhash constraints (on Solana)
</Accordion>

<Accordion title="Can I dynamically add policies per limit order without user friction?">
  Yes — this is a common pattern. You can add a policy per order (limit, stop loss, TWAP, etc.) using either the end-user’s authenticated session or a Delegated Access (DA) user, as long as the DA user has the necessary permissions defined by policy.
</Accordion>

<Accordion title="What are common implementation patterns among Turnkey clients using Delegated Access?">
  Turnkey's Policy Engine shines through its flexibility. There are many different approaches you can take based on your requirements, but various themes we see include:

  * Using **broad policies** with business-controlled API keys
  * Using \*\*fine-grained policies, \*\*scoped to predictable transaction shapes
  * Using delegated access to implement **limit orders, automation flows, or advanced trading logic** (e.g. perps, TWAPs)
  * Ensuring **strong operational security** (e.g. tight scoping & expiring keys) is increasingly common
</Accordion>

### EVM and SVM-specific strategies

<Accordion title="Are time-bound transactions supported?">
  Yes, on Solana via `solana.tx.recent_blockhash`, which restricts a transaction’s validity to a \~60–90 second window. Not ideal for delayed executions (e.g. limit orders), but useful for immediate, single-use actions.
</Accordion>

<Accordion title="For EVM transactions, can I enforce token-specific or contract-specific limits?">
  Yes, though it’s limited today. You can inspect calldata (e.g., using `eth.tx.data[...]`) and enforce conditions like:

  ```javascript theme={"system"}
  eth.tx.to == '<TOKEN_CONTRACT>' &&
  eth.tx.data[0..4] == '<ERC20_FUNCTION_SELECTOR>'
  ```

  Granular support for calldata parsing and value limits is coming soon.
</Accordion>

<Accordion title="Is it safe to whitelist routers (e.g. Jupiter) in delegated access policies?">
  Not entirely. Even if you allowlist the router, it could still be abused to swap all assets. You can’t control downstream behavior unless you control the contract.

  > **Suggestion:** Only allow DA keys to interact with contracts you fully trust or control. Limit scope as much as possible (e.g., to specific instructions, amounts, or recipients).
</Accordion>
