# sessionKeys.prepareOperation

> Documentation index: [llms.txt](https://namera.ai/llms.txt).

Source: https://namera.ai/docs/sdk/reference/session-keys/prepare-operation

Prepare installation or removal on one configured network.

`namera.sessionKeys.prepareOperation()` prepare installation or removal on one configured network.



## Usage [#usage]

Install `@namera-ai/sdk` and set `NAMERA_API_KEY` on your backend. IDs and responses below are illustrative fixtures; replace IDs with your own resources.

<Tabs items={["index.ts", "client.ts"]}>
<Tab value="index.ts">

```ts title="index.ts"
import { namera } from "./client";
const result = await namera.sessionKeys.prepareOperation({
  sessionKeyId: "0199dfe1-0000-7000-8000-000000000003",
  chainId: "eip155:11155111",
  kind: "install",
  sponsor: true,
});
if (!result.success) throw new Error(result.error.message);

console.log(result.data);
```

</Tab>
<Tab value="client.ts">

```ts title="client.ts"
import { NameraClient } from "@namera-ai/sdk";

export const namera = new NameraClient({
  apiKey: process.env.NAMERA_API_KEY!,
});
```

</Tab>
</Tabs>

## Returns [#returns]

API methods return a `Promise<NameraResult<T, E>>`. When `success` is `true`,
`data` contains the value described below and `error` is `null`. On failure,
`data` is `null` and `error` describes the failure.

The JSON example shows the complete successful `data`, with illustrative values.
Date-time values use ISO strings in JSON; bigint values use decimal strings.
See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for the error shape.

Returns `operationId`, `namespace`, `approval`, `prepared`, and `expiresAt`. `approval` is `"1claw"` or `"passkey"`; passkey responses also include WebAuthn `options`. Preparation contains the exact stored installation/removal call, simulation, and gas information, but no owner signature.

<div className="docs-response">

```json
{
  "operationId": "0199dfe1-0000-7000-8000-000000000014",
  "namespace": "eip155",
  "approval": "1claw",
  "prepared": {
    "version": 1,
    "namespace": "eip155",
    "chainId": "eip155:11155111",
    "entryPointVersion": "0.7",
    "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
    "sponsorship": "alchemy-bso",
    "context": {
      "version": 1,
      "namespace": "eip155",
      "chainId": "eip155:11155111",
      "account": "0x3333333333333333333333333333333333333333",
      "block": {
        "number": "0",
        "hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "timestamp": "1970-01-01T00:00:00.000Z"
      },
      "calls": [
        {
          "to": "0x3333333333333333333333333333333333333333",
          "value": "0",
          "data": "0x1234"
        }
      ],
      "userOperation": {
        "nonce": "0",
        "gas": {
          "callGasLimit": "0",
          "verificationGasLimit": "0",
          "preVerificationGas": "0",
          "paymasterVerificationGasLimit": "0",
          "paymasterPostOpGasLimit": "0",
          "maxFeePerGas": "0",
          "maxPriorityFeePerGas": "0"
        },
        "paymaster": null
      },
      "simulation": {
        "userOperation": {
          "source": "eth_estimateUserOperationGas",
          "callGasLimit": "0",
          "verificationGasLimit": "0",
          "preVerificationGas": "0",
          "maxFeePerGas": "1000000000",
          "maxPriorityFeePerGas": "1"
        },
        "calls": {
          "source": "viem.simulateCalls",
          "results": [
            {
              "status": "success",
              "returnData": "0x",
              "gasUsed": "0"
            }
          ],
          "assetChanges": [],
          "transfers": []
        }
      }
    },
    "userOperation": {
      "sender": "0x3333333333333333333333333333333333333333",
      "nonce": "0",
      "callData": "0x",
      "callGasLimit": "0",
      "verificationGasLimit": "0",
      "preVerificationGas": "0",
      "maxFeePerGas": "0",
      "maxPriorityFeePerGas": "0",
      "signature": "0x"
    },
    "billing": {
      "executionMeter": "execution.testnet",
      "sponsorship": null
    }
  },
  "expiresAt": "2026-10-15T02:44:05.075Z"
}
```

</div>

Passkey approval uses this shape:

<div className="docs-response">

```json
{
  "operationId": "0199dfe1-0000-7000-8000-000000000021",
  "namespace": "eip155",
  "options": {
    "challenge": "ERERERERERERERERERERERERERERERERERERERERERE",
    "rpId": "app.example.com",
    "timeout": 300000,
    "allowCredentials": [
      {
        "id": "fH9q_W4I4NAClGWOrbumZv4mrefSBfKPdY2UFfTKvcI",
        "type": "public-key"
      }
    ],
    "userVerification": "required"
  },
  "prepared": {
    "version": 1,
    "namespace": "eip155",
    "chainId": "eip155:11155111",
    "entryPointVersion": "0.7",
    "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032",
    "sponsorship": "alchemy-bso",
    "context": {
      "version": 1,
      "namespace": "eip155",
      "chainId": "eip155:11155111",
      "account": "0x3333333333333333333333333333333333333333",
      "block": {
        "number": "0",
        "hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "timestamp": "1970-01-01T00:00:00.000Z"
      },
      "calls": [
        {
          "to": "0x3333333333333333333333333333333333333333",
          "value": "0",
          "data": "0x1234"
        }
      ],
      "userOperation": {
        "nonce": "0",
        "gas": {
          "callGasLimit": "0",
          "verificationGasLimit": "0",
          "preVerificationGas": "0",
          "paymasterVerificationGasLimit": "0",
          "paymasterPostOpGasLimit": "0",
          "maxFeePerGas": "0",
          "maxPriorityFeePerGas": "0"
        },
        "paymaster": null
      },
      "simulation": {
        "userOperation": {
          "source": "eth_estimateUserOperationGas",
          "callGasLimit": "0",
          "verificationGasLimit": "0",
          "preVerificationGas": "0",
          "maxFeePerGas": "1000000000",
          "maxPriorityFeePerGas": "1"
        },
        "calls": {
          "source": "viem.simulateCalls",
          "results": [
            {
              "status": "success",
              "returnData": "0x",
              "gasUsed": "0"
            }
          ],
          "assetChanges": [],
          "transfers": []
        }
      }
    },
    "userOperation": {
      "sender": "0x3333333333333333333333333333333333333333",
      "nonce": "0",
      "callData": "0x",
      "callGasLimit": "0",
      "verificationGasLimit": "0",
      "preVerificationGas": "0",
      "maxFeePerGas": "0",
      "maxPriorityFeePerGas": "0",
      "signature": "0x"
    },
    "billing": {
      "executionMeter": "execution.testnet",
      "sponsorship": null
    }
  },
  "expiresAt": "2026-10-15T02:44:06.347Z"
}
```

</div>

## Parameters [#parameters]

### sessionKeyId [#sessionkeyid]

Type: `string`. Required. Session UUID. The SDK reads this session to resolve its account owner and matching installation. Requires session read access.

```ts title="index.ts"
import { namera } from "./client";
const result = await namera.sessionKeys.prepareOperation({
  sessionKeyId: "0199dfe1-0000-7000-8000-000000000003", // [!code focus]
  chainId: "eip155:11155111",
  kind: "install",
  sponsor: true,
});
if (!result.success) throw new Error(result.error.message);

console.log(result.data);
```

### chainId [#chainid]

Type: `SupportedEvmChainId`. Required. Configured CAIP-2 network ID, such as `eip155:11155111`. This is not a numeric chain ID.

```ts title="index.ts"
import { namera } from "./client";
const result = await namera.sessionKeys.prepareOperation({
  sessionKeyId: "0199dfe1-0000-7000-8000-000000000003",
  chainId: "eip155:11155111", // [!code focus]
  kind: "install",
  sponsor: true,
});
if (!result.success) throw new Error(result.error.message);

console.log(result.data);
```

### kind [#kind]

Type: `"install" | "uninstall"`. Required. Choose installation or removal. Removal can target an installed network of an active or revoking session.

```ts title="index.ts"
import { namera } from "./client";
const result = await namera.sessionKeys.prepareOperation({
  sessionKeyId: "0199dfe1-0000-7000-8000-000000000003",
  chainId: "eip155:11155111",
  kind: "install", // [!code focus]
  sponsor: true,
});
if (!result.success) throw new Error(result.error.message);

console.log(result.data);
```

### sponsor [#sponsor]

Type: `boolean`. Optional; defaults to `true`. Whether to request gas sponsorship. Billing allowances still apply. Self-funded approval requires independent gas consent through the owner-approval validation helper.

```ts title="index.ts"
import { namera } from "./client";
const result = await namera.sessionKeys.prepareOperation({
  sessionKeyId: "0199dfe1-0000-7000-8000-000000000003",
  chainId: "eip155:11155111",
  kind: "install",
  sponsor: true, // [!code focus]
});
if (!result.success) throw new Error(result.error.message);

console.log(result.data);
```

## Behavior and errors [#behavior-and-errors]

Requires `session-key:read` plus `session-key:install` or `session-key:uninstall`. Preparation never signs or submits. The SDK generates and reuses one idempotency key across transient retries. A new call gets a new key; use `getActiveOperation()` to recover an interrupted operation. `OPERATION_BUSY` means another owner operation occupies that account/network. `INVALID_TRANSITION` means the session or installation cannot enter the requested transition. Callers must validate preparations against independently reviewed authority before approval; these are low-level transport methods, like execution prepare/complete.
