# Accounts and Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/accounts-and-session-keys Find accounts, inspect permissions, and import a session key. ## Find an Account [#find-an-account] ```sh namera wallet list namera wallet get ``` The second command opens an account picker. The CLI uses `wallet` in command names for the accounts shown in the dashboard.
```text πŸ‘› Example account | Active -> Address: 0x1111111111111111111111111111111111111111 -> Network type: EVM -> Custody: Namera-managed -> Description: SDK test account -> Created: 11 Oct 2026, 09:00:00 UTC ```
## Inspect a Session Key [#inspect-a-session-key] ```sh namera session-key list --wallet 0199dfe1-0000-7000-8000-000000000001 namera session-key get 0199dfe1-0000-7000-8000-000000000002 ``` Replace both IDs with your resources. The detail view separates installed network permissions from API policies:
```text Example session | Active -> Account: Example account -> Description: Send 0.001 test ETH on Base Sepolia -> Created: 11 Oct 2026, 09:05:00 UTC -> Expires: 11 Nov 2026, 09:00:00 UTC -> Networks: Base Sepolia Permissions Base Sepolia | Installed -> Starts: 11 Oct 2026, 09:00:00 UTC -> Message signing: Not allowed -> Contract access Address: 0x2222222222222222222222222222222222222222 -> Native token transfer Allowance: 1000000000000000 Unit: wei API Policies -> None ```
An active key still needs an installed, unexpired authorization on the network you want to use. A transfer permission does not automatically permit message signing. ## Import an Encrypted Key [#import-an-encrypted-key] Use the import command provided by the dashboard: ```sh namera session-key import --host https://api.namera.ai ``` Enter the export passphrase when prompted. Import is local and requires no API login. It saves an encrypted file protected by an independent OS-keyring secret.
```text Session key imported Status: imported Session Key ID: 0199dfe1-0000-7000-8000-000000000002 Wallet ID: 0199dfe1-0000-7000-8000-000000000001 Chains: eip155:84532 ```
Import does not install permissions or grant CLI access. Approve a network in the dashboard, wait for the key to become active, then log in and select it. Only import keys on machines you trust. The CLI resolves imported keys automatically when running as the same OS user against the matching API origin. See [Import a Session Key](https://namera.ai/docs/cli/reference/session-keys/session-key-import) for storage and recovery details. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Authentication > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/authentication Sign in from your terminal or use an API key for automation. ## Sign In with Your Browser [#sign-in-with-your-browser] ```sh namera login ``` Approve the connection and select active session keys in the browser. If the browser does not open, use the verification URL and code printed in the terminal. The command waits for approval and saves credentials in your OS keyring.
```text OK Signed in as "personal". -> Run namera wallet list to see your wallets. ```
Use a named connection for another workspace: ```sh namera login --profile work --device-name "Work laptop" namera auth status --profile work ``` The CLI refreshes saved OAuth credentials when possible. If a connection expires or is revoked, sign in again with the same profile. ## Use an API Key [#use-an-api-key] Set `NAMERA_API_KEY` through your shell's secret manager or CI secret store, then: ```sh namera auth status ```
```text OK Connected with an API key Profile: automation Organization: Example workspace Session keys Example account -> πŸ”‘ Example session | Active | Expires in 31 days ```
An API key takes precedence over saved CLI credentials, even when you pass `--profile`. Unset it to return to browser-based login: ```sh unset NAMERA_API_KEY namera auth status --profile personal ``` Do not put the key in command arguments, source files, or logs. ## Review Access [#review-access] ```sh namera session-key list namera session-key get ``` Authentication identifies the caller. Grants select usable session keys; installed permissions and policies restrict what those keys can do. Individual operation flags also need account and session-key read access to validate selections. ## Sign Out [#sign-out] ```sh namera logout --profile personal ```
```text OK Signed out of "personal" on this device. -> Run namera login to reconnect. Your imported keys are still saved. ```
Logout removes the saved CLI connection on this device. It does not delete imported keys or revoke the authorization on the server. Revoke that authorization in the dashboard to end its server-side access. MCP has [separate credentials](https://namera.ai/docs/cli/reference/mcp/login). Ordinary login and `NAMERA_API_KEY` do not authorize an MCP client. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Getting Started > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/getting-started Connect your terminal, inspect an account, and send a test transaction. ## Install the CLI [#install-the-cli] ```sh npm install -g @namera-ai/cli ``` Use Node.js 24.14+ and an unlocked OS keyring. ## Set Up Your Account [#set-up-your-account] In the [Namera dashboard](https://dashboard.namera.ai), create or choose an account. Choose a separate recipient address you control on **Base Sepolia**. Create a session key that permits a **0.001 ETH** transfer to that recipient. If the dashboard gives you an encrypted import command, run it on this machine and enter the export passphrase privately: ```sh namera session-key import --host https://api.namera.ai ``` Approve the key's installation on Base Sepolia in the dashboard. Wait until it is active, and fund the account with test ETH. Importing alone does not approve network access. ## Sign In [#sign-in] ```sh namera login ``` Approve the requested access and select your active session key in the browser. After approval:
```text OK Signed in as "personal". -> Run namera wallet list to see your wallets. ```
## List Accounts and Session Keys [#list-accounts-and-session-keys] ```sh namera wallet list ```
```text Found 1 delegated wallet: πŸ‘› Example account | Active -> Address: 0x1111111111111111111111111111111111111111 -> Network type: EVM -> Custody: Namera-managed -> Description: SDK test account -> Created: 11 Oct 2026, 09:00:00 UTC ```
```sh namera session-key list ```
```text πŸ‘› Example account πŸ”‘ Example session | Active | Expires in 31 days -> Networks: Base Sepolia ```
Use `namera wallet get` or `namera session-key get` to choose a resource and inspect its details. Use `--output json` when you need IDs for scripts. ## Simulate the Transfer [#simulate-the-transfer] ```sh namera execution simulate ``` Choose EVM, your account and session key, then Base Sepolia. Enter your recipient, `1000000000000000` for the amount in wei (0.001 ETH), and `0x` for calldata.
```text Transaction preview -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Policy decision: Allowed -> Calls: Succeeded Simulation only. No transaction was submitted. ```
Simulation does not submit a transaction. An allowed preview is not a guarantee that a later execution will succeed. ## Execute the Transfer [#execute-the-transfer] ```sh namera execution execute ``` Enter the same inputs and choose sponsored gas when prompted. This command submits the transaction; prompts collect inputs, not a dry run. Select Base Sepolia and a recipient you control. The amount is entered in wei: `1000000000000000` is 0.001 ETH.
```text -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
## Check the Submission [#check-the-submission] Use the submission ID printed by your command: ```sh namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
```text -> Status: Pending confirmation -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
Keep checking that ID until the status is Confirmed or Failed. Do not rerun `execute` to check progress. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. Next, use [Transfer Assets](https://namera.ai/docs/cli/guides/transactions/transfer-assets) for explicit flags or [Connect Codex](https://namera.ai/docs/cli/guides/automation/connect-codex) to give an agent access. # Connect Claude Code > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/automation/connect-claude-code Give Claude Code access to Namera through local MCP. Install the [Namera CLI](https://namera.ai/docs/cli/installation) and Claude Code on the machine that will run the agent. Make sure `namera` is on that process's PATH. Complete account setup and any required key import on the same machine. ## Register Namera [#register-namera] ```sh claude mcp add --transport stdio --scope user namera -- namera mcp serve --profile claude ``` User scope makes the connection available across your local Claude Code projects. The client launches a local stdio process. You do not need to start a background daemon or configure a hosted MCP URL. ## Authorize the Connection [#authorize-the-connection] You can authorize before the first tool call: ```sh namera mcp login --profile claude namera mcp status --profile claude ```
```text OK MCP connected to Namera -> Profile: claude -> Server: https://api.namera.ai Permissions -> View wallets, session keys, and transaction history -> Send transactions and sign with authorized session keys -> Stay connected ```
Approve only the active session keys and permissions this agent needs. Ordinary `namera login` and `NAMERA_API_KEY` do not authorize the MCP connection. If you skip manual login, the first authenticated tool call opens browser consent and asks you to retry after approval. If the browser cannot open, follow the URL printed by `namera mcp login`. ## Check Read Access First [#check-read-access-first] Ask the agent to list your Namera accounts and inspect a session key before requesting an execution. Read access and execute/sign access are separate. To send transactions, the selected key must also permit the target network and action. For self-funded gas, configure an explicit ceiling on the `mcp serve` command. Tools cannot raise that ceiling; see [Sponsor Gas](https://namera.ai/docs/cli/guides/transactions/sponsor-gas). ## Disconnect [#disconnect] ```sh namera mcp logout --profile claude ``` This revokes the MCP connection without deleting imported keys. Remove the MCP registration from the agent client separately if you no longer want it launched. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Connect Codex > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/automation/connect-codex Give Codex access to Namera through local MCP. Install the [Namera CLI](https://namera.ai/docs/cli/installation) and Codex on the machine that will run the agent. Make sure `namera` is on that process's PATH. Complete account setup and any required key import on the same machine. ## Register Namera [#register-namera] ```sh codex mcp add namera -- namera mcp serve --profile codex ``` The client launches a local stdio process. You do not need to start a background daemon or configure a hosted MCP URL. ## Authorize the Connection [#authorize-the-connection] You can authorize before the first tool call: ```sh namera mcp login --profile codex namera mcp status --profile codex ```
```text OK MCP connected to Namera -> Profile: codex -> Server: https://api.namera.ai Permissions -> View wallets, session keys, and transaction history -> Send transactions and sign with authorized session keys -> Stay connected ```
Approve only the active session keys and permissions this agent needs. Ordinary `namera login` and `NAMERA_API_KEY` do not authorize the MCP connection. If you skip manual login, the first authenticated tool call opens browser consent and asks you to retry after approval. If the browser cannot open, follow the URL printed by `namera mcp login`. ## Check Read Access First [#check-read-access-first] Ask the agent to list your Namera accounts and inspect a session key before requesting an execution. Read access and execute/sign access are separate. To send transactions, the selected key must also permit the target network and action. For self-funded gas, configure an explicit ceiling on the `mcp serve` command. Tools cannot raise that ceiling; see [Sponsor Gas](https://namera.ai/docs/cli/guides/transactions/sponsor-gas). ## Disconnect [#disconnect] ```sh namera mcp logout --profile codex ``` This revokes the MCP connection without deleting imported keys. Remove the MCP registration from the agent client separately if you no longer want it launched. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Connect Other MCP Clients > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/automation/connect-other-mcp-clients Run Namera as a local stdio server in an MCP-compatible client. ## Configure the Command [#configure-the-command] Install the [CLI](https://namera.ai/docs/cli/installation) on the machine that will run the MCP process. Configure these fields in your client's stdio server settings: - **Name:** `namera` - **Command:** `namera` - **Arguments:** `["mcp", "serve", "--profile", "agent"]` Clients using an `mcpServers` JSON configuration commonly accept: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "agent"] } } } ``` The outer configuration format depends on your client. If it cannot find the executable, use the absolute installed path in `command`. Keep stdout reserved for MCP; do not add shell banners or wrappers that print there. ## Authorize [#authorize] ```sh namera mcp login --profile agent namera mcp status --profile agent ```
```text OK MCP connected to Namera -> Profile: agent -> Server: https://api.namera.ai Permissions -> View wallets, session keys, and transaction history -> Send transactions and sign with authorized session keys -> Stay connected ```
Use the same OS user, profile, and API host in both the client configuration and login command. For a custom deployment, append `--host` and its origin to the configured argument list and every MCP management command. ## Use the Tools [#use-the-tools] Namera exposes account and session-key reads, transaction simulation and execution, status and history reads, signing, and signature verification. Start with a read to confirm the intended organization and grants. The first authenticated tool call can start browser consent automatically. Approve it, then retry the tool. Login credentials survive client restarts; imported signing keys must also be available on that machine. ## Diagnose a Connection [#diagnose-a-connection] If status says `login-required`, sign in again. If the client cannot launch Namera, check its PATH and Node.js version. If tools are denied, review the connection's scopes and session-key permissions. Do not treat a lost execution response as permission to repeat the transfer. See [mcp serve](https://namera.ai/docs/cli/reference/mcp/serve) for supported protocol versions, host requirements, and the gas ceiling. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Run in Scripts and CI > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/automation/run-in-scripts-and-ci Use explicit inputs, JSON output, and a secret-backed credential. ## Authenticate Without Browser Prompts [#authenticate-without-browser-prompts] Install Node.js 24.14+ and the CLI. Supply `NAMERA_API_KEY` through your CI secret store, not a committed configuration file or command-line argument. Pin the CLI version used by the job to a release you have tested. ```sh npm install -g @namera-ai/cli@1.2.0 namera --output json wallet list ```
```json [ { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" } } ] ```
API keys take precedence over saved CLI login profiles. For another deployment, also supply `NAMERA_API_URL`. ## Separate Results from Errors [#separate-results-from-errors] This POSIX shell example requires `jq` and uses an existing submission ID: ```sh submission_id='0199dfe1-0000-7000-8000-000000000003' if namera --output json execution status "$submission_id" > status.json 2> error.json; then status=$(jq -r '.status' status.json) case "$status" in confirmed) printf '%s\n' 'Confirmed' ;; failed) printf '%s\n' 'Submission failed' >&2; exit 1 ;; *) printf '%s\n' 'Still pending; check this ID again later' ;; esac else jq -r '.error | "\(.code): \(.message)\n\(.nextStep)"' error.json >&2 exit 1 fi ``` Do not merge stderr into stdout when parsing JSON. The CLI prints successful data directly, not under a `data` field. ## Make Inputs Explicit [#make-inputs-explicit] JSON output, quiet mode, and redirected streams disable missing-input prompts. Supply all operation flags, or pass one complete `--params` request. See [Interactive and Scripted Usage](https://namera.ai/docs/cli/interactive-and-scripted-usage). For imports, the export passphrase remains interactive. A local signing key must already be available to the runner's OS user and keyring. API-key authentication alone does not provide signing-key material. Do not put private keys or keyring unlock secrets into command arguments. ## Preserve Submission State [#preserve-submission-state] Store a successful execution's `submissionId` with the job in durable storage. Avoid duplicate workers and automatic whole-command execution retries. A job that lost its response needs [reconciliation](https://namera.ai/docs/cli/guides/transactions/handle-retries-and-recovery), not an immediate replacement transfer. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Sign Messages > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/signing/sign-messages Create an account signature for a UTF-8 message. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. The key must allow message signing on that network. Transfer-only permissions are not sufficient. ## Sign the Message [#sign-the-message] ```sh namera sign \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --type message \ --message 'Hello from Namera' ```
```text Signature created -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Type: Message -> Signature: 0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b ```
The command does not broadcast a transaction. The signature is for the smart account, not a plain externally owned account signature. ## Save the Signature [#save-the-signature] Use `--output json` when passing the signature to another application: ```sh namera --output json sign \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --type message \ --message 'Hello from Namera' ``` This is another signing operation, not a read of the previous result. Choose the output mode before signing rather than rerunning just to change formatting.
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "signature": "0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b", "type": "message" } ```
Keep the original message, account, and network with the signature. Use [Verify Signatures](https://namera.ai/docs/cli/guides/signing/verify-signatures) to check it. The fixture signature shown here is illustrative, not a signature to reuse. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Sign Typed Data > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/signing/sign-typed-data Sign an EIP-712 payload with explicit application context. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. Enable signature authority and permit the intended typed-data domain. Confirm the domain's chain ID and verifying contract before signing. ## Prepare the Payload [#prepare-the-payload] Save this example as `typed-data.json`, replacing the domain with your application's real values: ```json title="typed-data.json" { "domain": { "name": "Namera Example", "version": "1", "chainId": 84532, "verifyingContract": "0x2222222222222222222222222222222222222222" }, "types": { "Note": [ { "name": "contents", "type": "string" } ] }, "primaryType": "Note", "message": { "contents": "Hello from Namera" } } ``` The domain's numeric `chainId` and the CLI's selected network serve different roles. Keep them consistent for a payload intended for that network. ## Sign the Payload [#sign-the-payload] ```sh namera sign \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --type typed-data \ --typed-data "$(cat typed-data.json)" ```
```text Signature created -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Type: Typed data (EIP-712) -> Signature: 0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b ```
With `--output json` on the signing command:
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "signature": "0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b", "type": "typed-data" } ```
Use `--output json` on the original invocation if another program will consume the signature. Keep the complete typed-data object unchanged for verification. Do not combine `--message` with `--typed-data`. The example signature is a fixture value. A signature may authorize an action even though this command itself does not submit a transaction. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Verify Signatures > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/signing/verify-signatures Check a signature using the original account, network, and payload. Install the CLI and [authenticate](https://namera.ai/docs/cli/authentication). Use the full signature returned by `namera sign`, not the illustrative signature from a documentation response. ## Verify a Message [#verify-a-message] ```sh namera verify-signature \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --network 'Base Sepolia' \ --type message \ --message 'Hello from Namera' \ --signature ```
```text Signature valid -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Type: Message ```
Use the exact original message, including spaces and line breaks. Verification checks the account; it takes no session-key ID. ## Verify Typed Data [#verify-typed-data] Save the original EIP-712 payload as `typed-data.json`, then: ```sh namera --output json verify-signature \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --network 'Base Sepolia' \ --type typed-data \ --typed-data "$(cat typed-data.json)" \ --signature ``` For scripts, inspect `valid` in the returned JSON. A successful request with `valid: false` is not a command error. Do not treat exit code zero as a valid signature. Verification does not submit a transaction or prove which session key signed. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Batch Transactions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/batch-transactions Submit multiple calls in one execution request. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. This example sends **0.001 ETH to each of two recipients**. Fund the account with the total amount, and permit both targets and a total native spend of 0.002 ETH. ## Build the Request [#build-the-request] Save this as `batch.json`, replacing the example IDs and recipients: ```json title="batch.json" { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002", "chainId": "eip155:84532", "calls": [ { "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000", "data": "0x" }, { "to": "0x3333333333333333333333333333333333333333", "value": "1000000000000000", "data": "0x" } ], "sponsor": true } ``` The CLI's individual flags describe one call. Use `--params` for a `calls` array. Amounts are decimal strings in wei, not JSON numbers or bigint literals. ## Submit the Batch [#submit-the-batch] ```sh namera execution execute --params "$(cat batch.json)" ```
```text -> Network: Base Sepolia -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
One submission ID tracks the whole execution. `--params` skips interactive account/key selection, so the human output shows the network without fetching names for that selection. Do not combine `--params` with `--wallet`, `--to`, or other input flags. Keep `sponsor` inside the JSON request. For self-funded gas, set it to `false` and supply `--max-gas-cost-wei` alongside `--params`. Save the submission ID and [track it](https://namera.ai/docs/cli/guides/transactions/track-transactions). Do not repeat the execution to check progress. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Handle Retries and Recovery > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/handle-retries-and-recovery Recover from interrupted commands without sending duplicate transactions. ## Keep the Submission ID [#keep-the-submission-id] When submitting from a script, save the successful JSON result in durable job storage. Keep the original request with it. Human output also prints a status command while the submission is pending. A successful command can return a queued operation, not a confirmed transfer. ## Retry Reads, Not Transfers [#retry-reads-not-transfers] ```sh namera --output json execution status 0199dfe1-0000-7000-8000-000000000003 ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
This is safe to repeat for the same submission. If authorization fails, restore the connection before checking again. If rate-limited, follow the error's recovery instruction before retrying. By contrast, a new `execution execute` command creates a new operation. Do not wrap it in a generic shell retry loop. The transaction may already be queued or submitted. Check the existing submission before allowing another execution. ## Understand Internal Retries [#understand-internal-retries] Within a single execution, the SDK retries transient preparation and completion requests up to three times each. It reuses the operation's idempotency key or submission ID. It does not automatically retry policy denials or other declared business failures. There is no CLI flag to reuse an execution idempotency key across process restarts. A lost response is not proof that nothing was submitted. ## Recover a Lost Result [#recover-a-lost-result] If you know the submission ID, continue checking it. If you do not, mark the job unresolved and inspect the dashboard and confirmed execution history before allowing another attempt: ```sh namera execution list ``` An empty history does not rule out a pending operation. Compare the account, network, recipient, amount, and timing; matching values alone cannot uniquely identify repeated legitimate transfers. Fix a known rejection before intentionally submitting a replacement. Do not automatically repeat an uncertain signing command either, since another attempt can consume another signature allowance. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Interact with Contracts > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/interact-with-contracts Encode a contract call and execute it through a session key. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. Confirm the contract address and ABI from the contract's publisher. The key must allow the target and function. This example calls `setValue(uint256)` on a contract you control. ## Encode Calldata [#encode-calldata] ```sh npm install viem ``` ```js title="encode-call.mjs" import { encodeFunctionData, parseAbi } from "viem"; console.log( encodeFunctionData({ abi: parseAbi(["function setValue(uint256 value)"]), functionName: "setValue", args: [42n], }), ); ``` ## Simulate the Call [#simulate-the-call] ```sh calldata=$(node encode-call.mjs) namera execution simulate \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to \ --value 0 \ --data "$calldata" ```
```text Transaction preview -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Policy decision: Allowed -> Calls: Succeeded Simulation only. No transaction was submitted. ```
## Execute the Call [#execute-the-call] Use the same calldata and contract only after reviewing the preview: ```sh namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to \ --value 0 \ --data "$calldata" \ --sponsor true ```
```text -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
Save the submission ID and [track it](https://namera.ai/docs/cli/guides/transactions/track-transactions). Do not repeat the execution to check progress. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Simulate Transactions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/simulate-transactions Check calls and permissions before submitting. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. ## Run a Preview [#run-a-preview] This checks a 0.001 ETH transfer without sending it: ```sh namera execution simulate \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x ```
```text Transaction preview -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Policy decision: Allowed -> Calls: Succeeded Simulation only. No transaction was submitted. ```
## Inspect the Full Result [#inspect-the-full-result] Add `--output json` to read gas estimates, call results, asset changes, and transfers: ```sh namera --output json execution simulate \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "callsSucceeded": true, "simulation": { "userOperation": { "source": "eth_estimateUserOperationGas", "callGasLimit": "50000", "verificationGasLimit": "100000", "preVerificationGas": "50000", "maxFeePerGas": "1000000000", "maxPriorityFeePerGas": "1000000" }, "calls": { "source": "viem.simulateCalls", "results": [{ "status": "success", "returnData": "0x", "gasUsed": "21000" }], "assetChanges": [], "transfers": [ { "callIndex": 0, "from": "0x1111111111111111111111111111111111111111", "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000" } ] } }, "allowed": true, "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002" } ```
Review the simulated call results. Authorization and simulation failures return errors. Successful previews do not reserve billing allowance or guarantee later execution. For batch simulation, supply the simulation request through `--params` with a `calls` array. Do not include execution-only `sponsor` or gas-ceiling flags. ## Act on the Result [#act-on-the-result] If permission is denied, adjust the request or update the session's permissions in the dashboard. If a call fails, check its target, calldata, value, and account balance. A successful preview does not reserve permissions or guarantee the same chain state when you execute. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Sponsor Gas > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/sponsor-gas Choose sponsored execution or approve a self-funded gas ceiling. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. The transfer amount and gas budget are different. Even with sponsored gas, the account must hold the assets you are transferring. ## Use Sponsored Gas [#use-sponsored-gas] ```sh namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x \ --sponsor true ```
```text -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
Sponsored execution is subject to the account's permissions and Namera's applicable limits. An interactive execution prompts for sponsorship and defaults to Yes. ## Pay Gas from the Account [#pay-gas-from-the-account] Set sponsorship to false and approve an explicit maximum total gas cost in wei: ```sh namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x \ --sponsor false \ --max-gas-cost-wei 1000000000000000 ``` Here the transfer is 0.001 ETH and the gas ceiling is another 0.001 ETH. The ceiling is not a gas estimate or a promise that this amount will be spent. An operation whose prepared cost exceeds the ceiling is rejected. For `--params`, put `"sponsor": false` in the request and pass `--max-gas-cost-wei` as a separate CLI option. ## Set an Agent's Ceiling [#set-an-agents-ceiling] ```sh namera mcp serve --profile agent --max-gas-cost-wei 1000000000000000 ``` Configure that option in the command your MCP client launches. Without a ceiling, the process permits sponsored operations only. A tool call cannot raise it. Save the submission ID and [track it](https://namera.ai/docs/cli/guides/transactions/track-transactions). Do not repeat the execution to check progress. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Track Transactions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/track-transactions Follow an existing submission and inspect confirmed history. ## Check a Submission [#check-a-submission] Use the ID returned by `execution execute`, not a transaction or UserOp hash: ```sh namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
```text -> Status: Pending confirmation -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
The command checks once. Repeat this read until it reaches Confirmed or Failed. Queued and Pending confirmation are not terminal states. ## Save Machine-Readable Status [#save-machine-readable-status] ```sh namera --output json execution status 0199dfe1-0000-7000-8000-000000000003 ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
A confirmed response includes the full execution record. A failed response contains its submission ID and status, without an invented failure reason. See [execution status](https://namera.ai/docs/cli/reference/executions/status) for the state list. ## Read Confirmed History [#read-confirmed-history] ```sh namera execution list ```
```text Found 1 confirmed execution: -> Account: πŸ‘› Example account -> Transaction Hash: 0x5555555555555555555555555555555555555555555555555555555555555555 -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 -> Network: Base Sepolia -> Actor: Example integration (API Key) -> Session key: Example session ```
Use JSON to obtain `items` and `nextCursor`. When the cursor is not `null`, pass it to `--cursor` on the next read. History contains confirmed executions only. It is not a list of pending submissions. If a result was lost, follow [Handle Retries and Recovery](https://namera.ai/docs/cli/guides/transactions/handle-retries-and-recovery). Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Transfer Assets > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/guides/transactions/transfer-assets Send native tokens or ERC-20 tokens from your account. Install the CLI and [sign in](https://namera.ai/docs/cli/authentication). Replace the example account ID, session-key ID, and recipient with your own. Use an active key installed on **Base Sepolia** with permission for the operation. ## Transfer ETH [#transfer-eth] Fund the account with test ETH. Permit the recipient and a 0.001 ETH transfer in the session's network permissions. ```sh namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x \ --sponsor true ``` `--value 1000000000000000` is **0.001 ETH in wei**. `--data 0x` sends no contract calldata.
```text -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
## Transfer an ERC-20 Token [#transfer-an-erc-20-token] Permit the token contract, recipient, and amount in the session key. Encode the token's `transfer` call with viem; install it in your working project first: ```sh npm install viem ``` Save this as `transfer.mjs`. Replace the recipient, token amount, and decimals with values verified for your token: ```js title="transfer.mjs" import { encodeFunctionData, parseAbi, parseUnits } from "viem"; console.log( encodeFunctionData({ abi: parseAbi(["function transfer(address to, uint256 amount) returns (bool)"]), functionName: "transfer", args: ["0x2222222222222222222222222222222222222222", parseUnits("1", 6)], }), ); ``` Use the token contract as the target, not the recipient. The token amount is encoded in calldata; `--value 0` attaches no ETH: ```sh calldata=$(node transfer.mjs) namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to \ --value 0 \ --data "$calldata" \ --sponsor true ``` The command returns the same submission shape shown above. Simulate unfamiliar token calls before executing them. Save the submission ID and [track it](https://namera.ai/docs/cli/guides/transactions/track-transactions). Do not repeat the execution to check progress. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Overview > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli Inspect accounts, execute transactions, and sign from your terminal. The Namera CLI connects your terminal and AI agents to accounts through authorized session keys. Use prompts to explore, explicit flags for scripts, or the built-in MCP server to connect an agent. ## Quick Examples [#quick-examples] Install the [CLI](https://namera.ai/docs/cli/installation), complete [account setup](https://namera.ai/docs/cli/getting-started), and sign in with `namera login`. ### List Accounts [#list-accounts] ```sh namera wallet list ```
```text Found 1 delegated wallet: πŸ‘› Example account | Active -> Address: 0x1111111111111111111111111111111111111111 -> Network type: EVM -> Custody: Namera-managed -> Description: SDK test account -> Created: 11 Oct 2026, 09:00:00 UTC ```
### Sign a Message [#sign-a-message] ```sh namera sign --type message --message 'Hello from Namera' ``` In a terminal, choose the account, session key, and network when prompted. The key must allow signatures on that network.
```text Signature created -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Type: Message -> Signature: 0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b ```
### Execute a Transaction [#execute-a-transaction] ```sh namera execution execute ``` Choose an account and key, then supply the network, recipient, value in wei, calldata, and gas sponsorship choice. The command submits the transaction. Use `namera execution simulate` for a preview instead.
```text -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
Save the submission ID and check it with `namera execution status`. Submission is not confirmation. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. ## Choose Your Next Step [#choose-your-next-step] - [Getting Started](https://namera.ai/docs/cli/getting-started): send a first test transaction. - [Interactive and Scripted Usage](https://namera.ai/docs/cli/interactive-and-scripted-usage): choose prompts, flags, or JSON input. - [Connect Codex](https://namera.ai/docs/cli/guides/automation/connect-codex) or [Connect Claude Code](https://namera.ai/docs/cli/guides/automation/connect-claude-code): authorize an agent through MCP. - [Command Reference](https://namera.ai/docs/cli/reference/global-options): inspect syntax, options, output, and error behavior. # Installation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/installation Install Namera and prepare your terminal. ## Requirements [#requirements] Use **Node.js 24.14+**. Browser login and imported session keys require an accessible OS keyring. On Linux, use a persistent Secret Service session for keys that must remain usable after reboot. ## Install [#install] ```sh npm install -g @namera-ai/cli ``` ```sh pnpm add -g @namera-ai/cli ``` ```sh yarn global add @namera-ai/cli ``` ```sh bun add -g @namera-ai/cli ``` The Yarn command requires Yarn Classic. With modern Yarn, use npm or pnpm for a global install. Bun can install the package; the executable still runs on Node.js. ```sh namera --version namera --help ``` ## Update [#update] ```sh npm install -g @namera-ai/cli@latest ``` Updating does not remove saved profiles or imported keys. Continue to [Getting Started](https://namera.ai/docs/cli/getting-started). # Interactive and Scripted Usage > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/interactive-and-scripted-usage Choose prompts for exploration and explicit inputs for scripts. ## Use Prompts [#use-prompts] ```sh namera wallet get namera session-key get namera execution simulate namera execution execute namera sign namera verify-signature ``` Use arrow keys and Enter to select, or Ctrl+C to cancel. Operation prompts collect the network family, account, session key where needed, network, and payload. Supplying a flag skips its corresponding prompt. ## Supply Every Input [#supply-every-input] With JSON output, quiet mode, or redirected input/output, operation commands do not prompt for missing inputs. Provide every required flag, including zero values and empty calldata: ```sh namera --output json execution simulate \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x ``` Replace example IDs and addresses before running. For execution, also provide `--sponsor true`, or `--sponsor false` with `--max-gas-cost-wei`. `session-key import` is different: it always asks privately for the export passphrase. There is no passphrase flag for unattended imports. ## Pass a JSON Request [#pass-a-json-request] Use `--params` for [batch transactions](https://namera.ai/docs/cli/guides/transactions/batch-transactions) or a request built by your application. Do not mix it with individual payload flags. Shell examples use POSIX quoting and line continuation. In PowerShell, use its quoting rules or put a command on one line. JSON amounts representing bigint values must be decimal strings. ## Read Output [#read-output] Human output summarizes the result. JSON output preserves the complete data and IDs, with bigint quantities encoded as strings. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors) before building automation. # Output and Errors > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/output-and-errors Read human summaries, parse JSON, and handle command failures. ## Human Output [#human-output] ```sh namera wallet list ```
```text Found 1 delegated wallet: πŸ‘› Example account | Active -> Address: 0x1111111111111111111111111111111111111111 -> Network type: EVM -> Custody: Namera-managed -> Description: SDK test account -> Created: 11 Oct 2026, 09:00:00 UTC ```
Status and permissions use terminal colors when supported. `NO_COLOR` disables colors; pipes and unsupported terminals use plain-text symbols. ## JSON Output [#json-output] ```sh namera --output json wallet list ```
```json [ { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" } } ] ```
The CLI prints one compact JSON value to stdout, not the SDK's `{ success, data, error }` envelope. Successful list commands can return an array or a paginated object. Bigint quantities are decimal strings. ## Quiet Mode [#quiet-mode] ```sh namera --quiet auth status ``` Successful output is suppressed, but the command still runs and failures remain visible on stderr. Quiet mode also disables operation-input prompts. ## Failures [#failures] A failed command exits nonzero. With `--output json`, stderr contains one structured error object:
```json { "error": { "code": "INVALID_EXPORT", "message": "The encrypted session-key export is invalid or incomplete.", "nextStep": "Copy the entire import command from the dashboard. Do not paste a private key.", "retryable": false } } ```
Use `error.code` for branching and `nextStep` for recovery. Do not parse human error text. Keep stdout and stderr separate when consuming JSON. A command can succeed while reporting `allowed: false`, `valid: false`, or a submission with `status: "failed"`. Check the returned fields as well as the exit status. A successful status lookup does not mean a successful transaction. ## Retry Safely [#retry-safely] Do not repeat an execution just because the response was lost. Check its saved submission ID, or reconcile the outcome first. Follow [Handle Retries and Recovery](https://namera.ai/docs/cli/guides/transactions/handle-retries-and-recovery). MCP reserves stdout for protocol messages and writes diagnostics to stderr. Do not parse its stdout as ordinary CLI JSON. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # Profiles and Configuration > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/profiles-and-configuration Keep terminal and agent connections separate. ## Use a Named CLI Profile [#use-a-named-cli-profile] ```sh namera login --profile work --device-name "Work laptop" namera wallet list --profile work ``` Pass the name on each command. Ordinary CLI commands default to `personal`; logging in to `work` does not change the command flag's default. For a development server: ```sh namera login --profile dev --host http://localhost:8080 namera wallet list --profile dev ``` Login saves the server origin with that profile. Ordinary commands do not have a `--host` flag; use the saved connection or API-key environment configuration. ## Understand Host Selection [#understand-host-selection] | Operation | API origin | | -------------------------------- | ------------------------------------------------------- | | Ordinary command with an API key | `NAMERA_API_URL`, then `https://api.namera.ai` | | Ordinary command with OAuth | Saved CLI profile | | `login` | `--host`, defaulting to `https://api.namera.ai` | | `session-key import` | `--host`, then `NAMERA_API_URL`, then saved CLI profile | | MCP commands | `--host`, defaulting to `https://api.namera.ai` | Before the first personal login, import defaults to the production API. For a new custom profile, provide `--host` when importing. ## Keep MCP Profiles Separate [#keep-mcp-profiles-separate] ```sh namera mcp login --profile codex namera mcp status --profile codex ```
```text OK MCP connected to Namera -> Profile: codex -> Server: https://api.namera.ai Permissions -> View wallets, session keys, and transaction history -> Send transactions and sign with authorized session keys -> Stay connected ```
MCP defaults to `default`, not `personal`. Its profile and API origin together identify a connection. Use the same values when serving, signing in, checking status, and signing out. ## Storage [#storage] Nonsecret profile configuration lives in `config.json` under: | System | Default directory | | ------- | -------------------------------------- | | macOS | `~/Library/Application Support/namera` | | Windows | `%APPDATA%\Namera` | | Linux | `~/.config/namera` | `XDG_CONFIG_HOME`, when set, takes precedence on every platform; Namera uses its `namera` subdirectory. Credentials are stored in the OS keyring. Imported session keys are encrypted files under `session-keys`, protected by keyring secrets. Changing directories does not migrate keyring entries. Keep your encrypted backup and avoid deleting storage to resolve an authentication error. Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. # namera wallet get > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/accounts/wallet-get Read one account by ID or choose it interactively. Read one account by ID or choose it interactively. ## Usage [#usage] ```sh namera wallet get 0199dfe1-0000-7000-8000-000000000001 ``` ## Output [#output]
```text πŸ‘› Example account | Active -> Address: 0x1111111111111111111111111111111111111111 -> Network type: EVM -> Custody: Namera-managed -> Description: SDK test account -> Created: 11 Oct 2026, 09:00:00 UTC ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. ```sh namera --output json wallet get 0199dfe1-0000-7000-8000-000000000001 ```
```json { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" } } ```
## Arguments [#arguments] ### wallet-id [#wallet-id] - **Type:** `string` (UUID) - **Required:** outside an interactive terminal Use an ID returned by `wallet list --output json`, not an address. Omit it in an interactive terminal to open a picker. The picker is unavailable with JSON output, quiet mode, or redirected streams. ## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera wallet list > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/accounts/wallet-list List the accounts available to your credential. List the accounts available to your credential. ## Usage [#usage] ```sh namera wallet list ``` ## Output [#output]
```text Found 1 delegated wallet: πŸ‘› Example account | Active -> Address: 0x1111111111111111111111111111111111111111 -> Network type: EVM -> Custody: Namera-managed -> Description: SDK test account -> Created: 11 Oct 2026, 09:00:00 UTC ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. For complete account records and IDs: ```sh namera --output json wallet list ```
```json [ { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" } } ] ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. The list is not paginated. An empty human result is `No delegated wallets found.`; JSON returns `[]`. This command reads accounts; it does not create them. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera auth status > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/authentication/auth-status Inspect the credential and permissions used by ordinary CLI commands. Inspect the credential and permissions used by ordinary CLI commands. ## Usage [#usage] ```sh namera auth status ``` ## Output [#output] With `NAMERA_API_KEY` supplied through the environment:
```text OK Connected with an API key Profile: automation Organization: Example workspace Session keys Example account -> πŸ”‘ Example session | Active | Expires in 31 days ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. ```sh namera --output json auth status ```
```json { "profile": "automation", "actor": { "type": "api-key", "data": { "actorId": "0199dfe1-0000-7000-8000-000000000014", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationName": "Example workspace", "grants": [ { "grant": { "id": "0199dfe1-0000-7000-8000-000000000013", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "actorId": "0199dfe1-0000-7000-8000-000000000014", "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002", "grantedByActorId": "0199dfe1-0000-7000-8000-000000000015", "revokedAt": null, "revokedByActorId": null, "createdAt": "2026-10-11T09:00:00.000Z" }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "createdByActorId": "0199dfe1-0000-7000-8000-000000000015", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "SDK test session" }, "policyHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "status": "active", "revokedAt": null, "revokedByActorId": null, "createdAt": "2026-10-11T09:00:00.000Z", "namespace": "eip155", "policies": [ { "id": "0199dfe1-0000-7000-8000-000000000016", "appliesTo": "signature", "type": "evm.chain-allowlist", "version": 1, "chainIds": ["eip155:84532"] } ] } } ], "apiKey": { "id": "0199dfe1-0000-7000-8000-000000000017", "metadata": { "version": 1, "name": "Example integration", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "SDK test credential" }, "keyStart": "example-prefix", "expiresAt": null, "lastUsedAt": "2026-10-11T09:10:00.000Z", "createdAt": "2026-10-11T09:00:00.000Z" } } } } ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. Human output may also read accounts and session keys to show their names and installation expiry when your scopes permit those reads. JSON returns `profile` and the full `actor` without those additional requests. This is an authenticated API check, not just a check for a saved token. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera login > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/authentication/login Authorize a terminal connection through your browser. Authorize a terminal connection through your browser. ## Usage [#usage] ```sh namera login ``` ## Output [#output]
```text OK Signed in as "personal". -> Run namera wallet list to see your wallets. ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. Before approval, the verification URL and code are printed to stderr. The successful JSON result contains `profile`, `status: "connected"`, and the full CLI `actor` record. No access or refresh token is printed.
```json { "profile": "personal", "status": "connected", "actor": { "type": "cli", "data": { "actorId": "0199dfe1-0000-7000-8000-000000000014", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationName": "Example workspace", "grants": [ { "grant": { "id": "0199dfe1-0000-7000-8000-000000000013", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "actorId": "0199dfe1-0000-7000-8000-000000000014", "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002", "grantedByActorId": "0199dfe1-0000-7000-8000-000000000015", "revokedAt": null, "revokedByActorId": null, "createdAt": "2026-10-11T09:00:00.000Z" }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "createdByActorId": "0199dfe1-0000-7000-8000-000000000015", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "SDK test session" }, "policyHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "status": "active", "revokedAt": null, "revokedByActorId": null, "createdAt": "2026-10-11T09:00:00.000Z", "namespace": "eip155", "policies": [ { "id": "0199dfe1-0000-7000-8000-000000000016", "appliesTo": "signature", "type": "evm.chain-allowlist", "version": 1, "chainIds": ["eip155:84532"] } ] } } ], "authorization": { "id": "0199dfe1-0000-7000-8000-000000000017", "clientId": "0199dfe1-0000-7000-8000-000000000018", "scopes": [ "wallet:read", "session-key:read", "execution:read", "execution:execute", "signature:create", "offline_access" ], "metadata": { "type": "cli", "version": 1, "deviceName": "Example laptop", "cliVersion": "1.2.0", "platform": "darwin" }, "expiresAt": null, "lastUsedAt": "2026-10-11T09:10:00.000Z", "createdAt": "2026-10-11T09:00:00.000Z" } } } } ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Save the connection under this name. Pass it to later commands with `--profile`. Logging in again replaces that profile's saved connection. ### --host [#--host] - **Type:** absolute API URL - **Default:** `https://api.namera.ai` Connect to this API origin. Login uses this flag, not `NAMERA_API_URL`. For local development, pass `--host http://localhost:8080`. ### --device-name [#--device-name] - **Type:** `string` - **Default:** `Namera CLI on ` Name shown during consent and in CLI execution history. Choose a recognizable device name without secrets: ```sh namera login --profile work --device-name "Work laptop" ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Browser Approval [#browser-approval] Approve access only to the active session keys this connection needs. If the browser cannot open, visit the printed URL and enter the code. Login waits for approval and expires if you do not complete it in time. Credentials are saved in the OS keyring. Imported signing keys are separate from the login connection. Use [Authentication](https://namera.ai/docs/cli/authentication) for API-key automation and sign-out behavior. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera logout > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/authentication/logout Remove a saved CLI connection from this device. Remove a saved CLI connection from this device. ## Usage [#usage] ```sh namera logout --profile personal ``` ## Output [#output]
```text OK Signed out of "personal" on this device. -> Run namera login to reconnect. Your imported keys are still saved. ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ.
```json { "profile": "personal", "status": "signed-out" } ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Remove this named CLI profile and its keyring credentials. This command targets the saved profile even if `NAMERA_API_KEY` is present. The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## What Remains [#what-remains] Imported signing keys are unchanged. Logout does not revoke the server-side OAuth authorization or an API key. Revoke access in the dashboard when necessary. Use `namera mcp logout` for the separate MCP connection. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # Environment Variables > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/environment-variables Configure credentials, API selection, storage, and terminal output. ## NAMERA_API_KEY [#namera_api_key] A secret API key for ordinary account, session-key, execution, signing, and auth status commands. When set, it takes precedence over saved CLI OAuth credentials and the selected profile. Obtain it from your workspace and supply it through a secret manager or CI secret store. It does not authorize MCP, affect local import authorization, or replace browser consent for `namera login`. Unset it to use a saved CLI connection. ## NAMERA_API_URL [#namera_api_url] The API URL used with `NAMERA_API_KEY`. If omitted, API-key commands use `https://api.namera.ai`. It also supplies the expected origin for `session-key import` when `--host` is absent. It does not override a saved OAuth profile, the login command's `--host`, or MCP's `--host`. ```sh NAMERA_API_URL=http://localhost:8080 namera --output json wallet list ``` This example assumes `NAMERA_API_KEY` is already supplied. ## XDG_CONFIG_HOME [#xdg_config_home] Base directory for configuration. When present, Namera uses its `namera` subdirectory on every platform. Otherwise it uses the OS-specific locations in [Profiles and Configuration](https://namera.ai/docs/cli/profiles-and-configuration). Changing it does not migrate saved credentials or keys. Do not use it to work around keyring errors. ## APPDATA [#appdata] On Windows, supplies the roaming application-data base directory when `XDG_CONFIG_HOME` is absent. Namera uses its `Namera` subdirectory. Otherwise the fallback is `AppData/Roaming/Namera` under the home directory. ## NO_COLOR [#no_color] Disable colored CLI output by setting this variable: ```sh NO_COLOR=1 namera wallet list ``` Output still uses readable summaries. Whether symbols use Unicode or ASCII also depends on terminal and locale support. `TERM=dumb`, redirected streams, and unsupported terminals use plain fallbacks; `FORCE_COLOR=0` disables colors too. ## Secret Handling [#secret-handling] The CLI does not load a project `.env` file automatically. Export variables through your shell or use your runner's environment configuration. Never commit API keys, OAuth tokens, private keys, or export passphrases. # namera execution execute > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/executions/execute Submit a transaction using an authorized session key. Submit a transaction using an authorized session key. ## Usage [#usage] ```sh namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x \ --sponsor true ``` ## Output [#output]
```text -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Status: Queued -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`, the successful submission data is:
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
Success means the request completed, not that the transaction is confirmed. Save `submissionId` and check it with `namera execution status`. ## Options [#options] ### --namespace [#--namespace] - **Type:** `evm | eip155` - **Required:** for non-interactive input flags Select the EVM network family. Both values resolve to the same namespace. This is not the chain ID; choose the network separately. ### --wallet [#--wallet] - **Type:** `string` (account ID) - **Required:** for non-interactive input flags Use an ID from `namera --output json wallet list`, not an Ethereum address. With input flags, the CLI reads the account to validate your selection. ### --network [#--network] - **Type:** network name, numeric chain ID, or CAIP-2 ID - **Required:** for non-interactive input flags For Base Sepolia, use `--network 'Base Sepolia'`, `--network 84532`, or `--network eip155:84532`. Names are case-insensitive. The supported networks are Ethereum, Sepolia, Base, Base Sepolia, Arbitrum One, Arbitrum Sepolia, OP Mainnet, and OP Sepolia. [Supported Networks](https://namera.ai/docs/sdk/supported-networks) lists their identifiers. ### --session-key [#--session-key] - **Type:** `string` (session-key ID) - **Required:** for non-interactive input flags Choose a key belonging to the selected account. Find IDs with `namera --output json session-key list --wallet `. Input flags require session-key read access to validate the key. Execution and signing also require a grant, an active installation on the chosen network, and matching permissions. ### --to [#--to] - **Type:** `0x`-prefixed Ethereum address - **Required:** for non-interactive input flags The recipient for a native-token transfer, or the contract receiving calldata. Use a full 20-byte address. The session key must permit this target. ### --value [#--value] - **Type:** non-negative integer string, in wei - **Required:** for non-interactive input flags The native-token amount attached to the call. `1000000000000000` means 0.001 ETH. Use `0` for a contract call that transfers no ETH. Decimal ETH amounts such as `0.001` are not accepted. ### --data [#--data] - **Type:** even-length `0x`-prefixed hex - **Required:** for non-interactive input flags ABI-encoded calldata for the target contract. Use `0x` for a plain ETH transfer. For token transfers, the token amount belongs in calldata, not `--value`. ### --sponsor [#--sponsor] - **Type:** `true | false` - **Required:** for non-interactive input flags Choose sponsored gas or payment from the account. The interactive prompt defaults to Yes. In `--params` JSON, omitting `sponsor` uses the API's sponsored default. ### --max-gas-cost-wei [#--max-gas-cost-wei] - **Type:** non-negative integer string, in wei - **Required:** for self-funded execution Set the largest gas cost you approve, separate from the transfer amount. This ceiling may be supplied alongside `--params`. With individual flags, an interactive self-funded request prompts if the ceiling is missing. ```sh namera execution execute \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x \ --sponsor false \ --max-gas-cost-wei 1000000000000000 ``` ### --params [#--params] - **Type:** JSON string - **Required:** only when replacing individual input flags Pass the complete request as one JSON object. Use this for batch calls or scripts that already construct requests. JSON uses `eip155` for the namespace, CAIP-2 chain IDs, and decimal strings for bigint quantities. Do not combine it with individual transaction or signature input flags. It can be used with `--profile` and global output options. Supplying JSON skips the interactive selection and its extra account/session-key reads; authorization and request validation still apply. ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Submission Safety [#submission-safety] The command submits once inputs are complete. It has no dry-run flag; use [simulate](https://namera.ai/docs/cli/reference/executions/simulate) first. A new invocation starts a new operation. Follow [recovery guidance](https://namera.ai/docs/cli/guides/transactions/handle-retries-and-recovery) before repeating a command after a lost response. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera execution list > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/executions/list Read confirmed transaction history. Read confirmed transaction history. ## Usage [#usage] ```sh namera execution list ``` ## Output [#output]
```text Found 1 confirmed execution: -> Account: πŸ‘› Example account -> Transaction Hash: 0x5555555555555555555555555555555555555555555555555555555555555555 -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 -> Network: Base Sepolia -> Actor: Example integration (API Key) -> Session key: Example session ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "items": [ { "details": { "id": "0199dfe1-0000-7000-8000-000000000012", "namespace": "eip155", "chainId": "eip155:84532", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "createdAt": "2026-10-11T09:10:00.000Z" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" } }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send test ETH on Base Sepolia" } }, "actorType": "api-key" } ], "nextCursor": null } ```
## Options [#options] ### --cursor [#--cursor] - **Type:** `string` (execution ID) - **Default:** first page Use the previous JSON response's `nextCursor` to continue. Stop when it is `null`. Keep the same credential and profile between requests. ```sh namera --output json execution list --cursor ``` ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. The CLI currently accepts only a cursor, not wallet, session-key, or page-size filters. Human output loads execution details to show readable names. JSON returns the original `items` and `nextCursor` without those extra reads. History contains confirmed executions only. An empty list does not establish that an interrupted submission failed; use its submission ID to check status. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera execution simulate > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/executions/simulate Preview calls and check installed permissions without submitting a transaction. Preview calls and check installed permissions without submitting a transaction. ## Usage [#usage] ```sh namera execution simulate \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --to 0x2222222222222222222222222222222222222222 \ --value 1000000000000000 \ --data 0x ``` ## Output [#output]
```text Transaction preview -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Policy decision: Allowed -> Calls: Succeeded Simulation only. No transaction was submitted. ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "callsSucceeded": true, "simulation": { "userOperation": { "source": "eth_estimateUserOperationGas", "callGasLimit": "50000", "verificationGasLimit": "100000", "preVerificationGas": "50000", "maxFeePerGas": "1000000000", "maxPriorityFeePerGas": "1000000" }, "calls": { "source": "viem.simulateCalls", "results": [{ "status": "success", "returnData": "0x", "gasUsed": "21000" }], "assetChanges": [], "transfers": [ { "callIndex": 0, "from": "0x1111111111111111111111111111111111111111", "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000" } ] } }, "allowed": true, "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002" } ```
## Options [#options] ### --namespace [#--namespace] - **Type:** `evm | eip155` - **Required:** for non-interactive input flags Select the EVM network family. Both values resolve to the same namespace. This is not the chain ID; choose the network separately. ### --wallet [#--wallet] - **Type:** `string` (account ID) - **Required:** for non-interactive input flags Use an ID from `namera --output json wallet list`, not an Ethereum address. With input flags, the CLI reads the account to validate your selection. ### --network [#--network] - **Type:** network name, numeric chain ID, or CAIP-2 ID - **Required:** for non-interactive input flags For Base Sepolia, use `--network 'Base Sepolia'`, `--network 84532`, or `--network eip155:84532`. Names are case-insensitive. The supported networks are Ethereum, Sepolia, Base, Base Sepolia, Arbitrum One, Arbitrum Sepolia, OP Mainnet, and OP Sepolia. [Supported Networks](https://namera.ai/docs/sdk/supported-networks) lists their identifiers. ### --session-key [#--session-key] - **Type:** `string` (session-key ID) - **Required:** for non-interactive input flags Choose a key belonging to the selected account. Find IDs with `namera --output json session-key list --wallet `. Input flags require session-key read access to validate the key. Execution and signing also require a grant, an active installation on the chosen network, and matching permissions. ### --to [#--to] - **Type:** `0x`-prefixed Ethereum address - **Required:** for non-interactive input flags The recipient for a native-token transfer, or the contract receiving calldata. Use a full 20-byte address. The session key must permit this target. ### --value [#--value] - **Type:** non-negative integer string, in wei - **Required:** for non-interactive input flags The native-token amount attached to the call. `1000000000000000` means 0.001 ETH. Use `0` for a contract call that transfers no ETH. Decimal ETH amounts such as `0.001` are not accepted. ### --data [#--data] - **Type:** even-length `0x`-prefixed hex - **Required:** for non-interactive input flags ABI-encoded calldata for the target contract. Use `0x` for a plain ETH transfer. For token transfers, the token amount belongs in calldata, not `--value`. ### --params [#--params] - **Type:** JSON string - **Required:** only when replacing individual input flags Pass the complete request as one JSON object. Use this for batch calls or scripts that already construct requests. JSON uses `eip155` for the namespace, CAIP-2 chain IDs, and decimal strings for bigint quantities. Do not combine it with individual transaction or signature input flags. It can be used with `--profile` and global output options. Supplying JSON skips the interactive selection and its extra account/session-key reads; authorization and request validation still apply. ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Interpreting the Preview [#interpreting-the-preview] Review the simulated call results. Authorization and simulation failures return errors. Successful previews do not reserve billing allowance or guarantee later execution. This command has no `--sponsor` or `--max-gas-cost-wei` flag. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera execution status > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/executions/status Read the state of an existing transaction submission. Read the state of an existing transaction submission. ## Usage [#usage] ```sh namera execution status 0199dfe1-0000-7000-8000-000000000003 ``` ## Output [#output]
```text -> Status: Pending confirmation -> UserOp Hash: 0x1111111111111111111111111111111111111111111111111111111111111111 Not confirmed yet. Check again with: namera execution status 0199dfe1-0000-7000-8000-000000000003 ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
## Arguments [#arguments] ### submission-id [#submission-id] - **Type:** `string` (UUID) - **Required:** yes Use the `submissionId` returned by execution, not a transaction hash, UserOp hash, or confirmed execution ID. The command checks once; repeat the read to poll. ## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Statuses [#statuses] | JSON status | Human label | Meaning | | ----------- | -------------------- | ---------------------------------------- | | `reserved` | Awaiting signature | Signing has not completed | | `prepared` | Queued | Signed and queued for broadcast | | `submitted` | Pending confirmation | Observed by the bundler | | `confirmed` | Confirmed | Successful execution record is available | | `failed` | Failed | Submission did not complete successfully | Confirmed JSON includes `execution`; failed JSON has no fabricated reason or hash. See [Get Submission Status](https://namera.ai/docs/sdk/reference/executions/get-submission-status) for complete response variants. Human confirmed output makes an additional execution-details read to show account and actor names. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # Global Options > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/global-options Control command output and access built-in help. Global flags can appear before the command: ```sh namera --output json wallet list ``` ## --output [#--output] - **Alias:** `-o` - **Type:** `pretty | json` - **Default:** `pretty` Choose readable summaries or full machine-readable data. JSON is one compact value on stdout, with bigint quantities represented as decimal strings. Failures are structured JSON on stderr. It is not an SDK result envelope. ```sh namera -o json session-key list ``` ## --quiet [#--quiet] - **Alias:** `-q` - **Type:** boolean - **Default:** `false` Suppress successful output without skipping the operation. Failures are still printed. Quiet mode disables operation prompts; supply required inputs explicitly. ```sh namera --quiet auth status ``` ## --help [#--help] - **Alias:** `-h` Show command syntax and available options without making an API request. ```sh namera --help namera execution execute --help ``` ## --version [#--version] - **Alias:** `-v` Print the installed CLI version. ```sh namera --version ``` ## --completions [#--completions] - **Type:** `bash | zsh | fish | sh` Print a shell-completion script. Review it and install it using your shell's completion setup. This flag prints the script; it does not edit shell startup files. ```sh namera --completions zsh ``` ## --wizard [#--wizard] Start the command framework's interactive wizard. For ordinary account and transaction selection, running the command without its input flags is usually sufficient. Wizards are not intended for redirected or unattended jobs. ## --log-level [#--log-level] - **Type:** `all | trace | debug | info | warn | warning | error | fatal | none` Set the framework's minimum log level. This is separate from `--output` and does not change result schemas or turn a failed command into a success. Do not publish diagnostic logs without checking them for sensitive information. ## Command-Specific Flags [#command-specific-flags] `--profile`, `--host`, and payload flags belong to specific commands, not the global flag set. Ordinary profiles default to `personal`; MCP profiles default to `default`. Not every command supports `--host`. MCP serving is a protocol process: `--output json` does not change its stdout into ordinary command output. # namera mcp login > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/mcp/login Authorize an MCP connection through browser consent. Authorize an MCP connection through browser consent. ## Usage [#usage] ```sh namera mcp login --profile default ``` ## Output [#output]
```text OK MCP connected to Namera -> Profile: default -> Server: https://api.namera.ai Permissions -> View wallets, session keys, and transaction history -> Send transactions and sign with authorized session keys -> Stay connected ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "profile": "default", "apiOrigin": "https://api.namera.ai", "status": "connected", "scopes": ["mcp:read", "mcp:execute", "offline_access"] } ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `default` Choose the MCP connection name. This is separate from ordinary CLI profiles, whose default is `personal`. Use the same name for `serve`, `login`, `status`, and `logout`. ### --host [#--host] - **Type:** absolute API URL - **Default:** `https://api.namera.ai` Choose the API origin for this MCP connection. The origin and profile together identify its saved credentials. Use HTTPS, or a loopback HTTP origin for local development. `NAMERA_API_URL` does not override this option on MCP commands. The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. This is separate from `namera login`. Approve only the session keys and MCP permissions the agent needs. Credentials persist in the OS keyring. If the browser cannot open, follow the printed URL. Imported signing keys must be available to the OS user running the MCP process. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera mcp logout > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/mcp/logout Revoke and disconnect an MCP connection. Revoke and disconnect an MCP connection. ## Usage [#usage] ```sh namera mcp logout --profile default ``` ## Output [#output]
```text OK MCP profile "default" disconnected. -> Your wallets and imported session keys are unchanged. ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "profile": "default", "status": "signed-out" } ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `default` Choose the MCP connection name. This is separate from ordinary CLI profiles, whose default is `personal`. Use the same name for `serve`, `login`, `status`, and `logout`. ### --host [#--host] - **Type:** absolute API URL - **Default:** `https://api.namera.ai` Choose the API origin for this MCP connection. The origin and profile together identify its saved credentials. Use HTTPS, or a loopback HTTP origin for local development. `NAMERA_API_URL` does not override this option on MCP commands. The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. Logout attempts server-side revocation and clears local authority. If revocation fails, the command reports an error; revoke the connection in the dashboard. Accounts and imported signing keys are not removed. Use ordinary `namera logout` to remove an ordinary CLI connection. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera mcp serve > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/mcp/serve Start the local stdio MCP server for an agent client. Start the local stdio MCP server for an agent client. ## Usage [#usage] ```sh namera mcp serve --profile default ``` ## Output [#output] This is a long-running protocol process, not a command that prints a result. Stdout contains MCP messages only; diagnostics and authorization instructions go to stderr. The client starts and stops the process. Closing stdin ends it. ## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `default` Choose the MCP connection name. This is separate from ordinary CLI profiles, whose default is `personal`. Use the same name for `serve`, `login`, `status`, and `logout`. ### --host [#--host] - **Type:** absolute API URL - **Default:** `https://api.namera.ai` Choose the API origin for this MCP connection. The origin and profile together identify its saved credentials. Use HTTPS, or a loopback HTTP origin for local development. `NAMERA_API_URL` does not override this option on MCP commands. ### --max-gas-cost-wei [#--max-gas-cost-wei] - **Type:** non-negative integer string, in wei - **Default:** sponsored operations only Approve a maximum gas cost for self-funded executions. MCP tools cannot raise this process-level ceiling. Omit it unless you intend to allow the agent to pay gas from the account. ```sh namera mcp serve --profile default --max-gas-cost-wei 1000000000000000 ``` `--output` and `--quiet` do not turn the stdio protocol into ordinary command output. Do not redirect stdout into a log file. ## Authorization [#authorization] Register this command with your MCP client instead of running a daemon manually. The first authenticated tool call starts browser authorization when needed. After approving it, retry the tool. Ordinary CLI login and `NAMERA_API_KEY` do not authorize MCP. Supported protocol versions are `2026-07-28`, `2025-11-25`, and `2025-06-18`. Negotiation is automatic; there is no protocol-version flag. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera mcp status > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/mcp/status Read the locally saved MCP connection state. Read the locally saved MCP connection state. ## Usage [#usage] ```sh namera mcp status --profile default ``` ## Output [#output]
```text OK MCP connected to Namera -> Profile: default -> Server: https://api.namera.ai Permissions -> View wallets, session keys, and transaction history -> Send transactions and sign with authorized session keys -> Stay connected ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "profile": "default", "apiOrigin": "https://api.namera.ai", "status": "connected", "scopes": ["mcp:read", "mcp:execute", "offline_access"] } ```
## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `default` Choose the MCP connection name. This is separate from ordinary CLI profiles, whose default is `personal`. Use the same name for `serve`, `login`, `status`, and `logout`. ### --host [#--host] - **Type:** absolute API URL - **Default:** `https://api.namera.ai` Choose the API origin for this MCP connection. The origin and profile together identify its saved credentials. Use HTTPS, or a loopback HTTP origin for local development. `NAMERA_API_URL` does not override this option on MCP commands. The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Status Values [#status-values] - **`connected`**: a saved credential has not expired. - **`refresh-required`**: the token has expired and a refresh token is saved. - **`login-required`**: no usable saved connection is available. This checks local state. It does not make an API request or prove server-side authorization remains valid. `scopes` lists saved scopes, which may remain present even when a new login is needed. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera session-key get > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/session-keys/session-key-get Read a session key's installed permissions and API policies. Read a session key's installed permissions and API policies. ## Usage [#usage] ```sh namera session-key get 0199dfe1-0000-7000-8000-000000000002 ``` ## Output [#output]
```text Example session | Active -> Account: Example account -> Description: Send 0.001 test ETH on Base Sepolia -> Created: 11 Oct 2026, 09:05:00 UTC -> Expires: 11 Nov 2026, 09:00:00 UTC -> Networks: Base Sepolia Permissions Base Sepolia | Installed -> Starts: 11 Oct 2026, 09:00:00 UTC -> Message signing: Not allowed -> Contract access Address: 0x2222222222222222222222222222222222222222 -> Native token transfer Allowance: 1000000000000000 Unit: wei API Policies -> None ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. ```sh namera --output json session-key get 0199dfe1-0000-7000-8000-000000000002 ```
```json { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000006", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send 0.001 test ETH on Base Sepolia" }, "policies": [], "policyHash": "1111111111111111111111111111111111111111111111111111111111111111", "status": "active", "revokedAt": null, "createdAt": "2026-10-11T09:05:00.000Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" } }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000000007", "userId": "0199dfe1-0000-7000-8000-000000000008", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationRoleId": "0199dfe1-0000-7000-8000-000000000009", "joinedAt": "2026-10-11T08:00:00.000Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000000008", "email": "developer@example.com", "emailVerified": true, "metadata": { "version": 1, "name": "Example developer", "image": { "type": "emoji", "value": "πŸ‘€" } }, "lastLoginAt": "2026-10-11T08:55:00.000Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000000009", "key": "developer", "permissions": [ "wallet:read", "wallet:create", "session-key:read", "session-key:create", "api-key:create" ], "metadata": { "version": 1, "name": "Developer", "logo": { "type": "emoji", "value": "πŸ’»" }, "description": "Manage test accounts and session keys" }, "type": "custom", "systemRoleId": null } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000010", "chainId": "eip155:84532", "status": "installed", "authorization": { "version": 1, "entityId": 1, "signerAddress": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf", "permissions": [ { "type": "contract-access", "address": "0x2222222222222222222222222222222222222222" }, { "type": "native-token-transfer", "allowance": "1000000000000000" } ], "allowSignatures": false, "validAfter": 1791709200, "validUntil": 1794387600 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ```
## Arguments [#arguments] ### session-key-id [#session-key-id] - **Type:** `string` (UUID) - **Required:** outside an interactive terminal Use an ID from `session-key list --output json`. Omit it in a terminal to pick a key by its name and account. Scripts, JSON output, and quiet mode require the ID. ## Options [#options] ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. Network approval and key status are distinct. Inspect the installation on the network you intend to use, along with its expiry and allowed actions. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera session-key import > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/session-keys/session-key-import Import a dashboard-encrypted session key onto this machine. Import a dashboard-encrypted session key onto this machine. ## Usage [#usage] ```sh namera session-key import --host https://api.namera.ai ``` ## Output [#output]
```text Session key imported Status: imported Session Key ID: 0199dfe1-0000-7000-8000-000000000002 Wallet ID: 0199dfe1-0000-7000-8000-000000000001 Chains: eip155:84532 ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. The command prompts for `Export passphrase` before printing this result. In JSON mode it returns `status`, `sessionKeyId`, `walletId`, and `chains`:
```json { "status": "imported", "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chains": ["eip155:84532"] } ```
## Arguments [#arguments] ### encrypted-export [#encrypted-export] - **Type:** base64url string - **Required:** yes Copy the full encrypted export from the dashboard's import command. It is not a private key or a file path. The export must match the expected API origin. Enter its passphrase at the hidden prompt; there is no passphrase flag. ## Options [#options] ### --host [#--host] - **Type:** absolute API URL - **Default:** environment or profile origin Use the host shown in the dashboard import command. Resolution order is `--host`, `NAMERA_API_URL`, then the saved CLI profile. An unsaved `personal` profile defaults to `https://api.namera.ai`; a new custom profile needs `--host`. ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Used to find the expected API origin when neither `--host` nor `NAMERA_API_URL` is provided. Import does not create a login profile. The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. ## Storage and Recovery [#storage-and-recovery] No API login is required. The CLI decrypts the export, then saves an encrypted file protected by an independent OS-keyring secret. It never falls back to plaintext. Import does not install the key onchain or grant access to a CLI/MCP connection. Approve a network in the dashboard, then authorize the active key during login. An already imported key is not overwritten. If import fails, preserve your encrypted export. Check the passphrase, origin, and OS-keyring access. On Linux, use persistent Secret Service; a memory-only keyring cannot retain unlock secrets across reboots. Do not use `sudo` or delete existing keys as a recovery shortcut. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera session-key list > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/session-keys/session-key-list List the session keys available to your credential. List the session keys available to your credential. ## Usage [#usage] ```sh namera session-key list --wallet 0199dfe1-0000-7000-8000-000000000001 ``` ## Output [#output]
```text πŸ‘› Example account πŸ”‘ Example session | Active | Expires in 31 days -> Networks: Base Sepolia ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. ```sh namera --output json session-key list --wallet 0199dfe1-0000-7000-8000-000000000001 ```
```json [ { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000006", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send 0.001 test ETH on Base Sepolia" }, "policies": [], "policyHash": "1111111111111111111111111111111111111111111111111111111111111111", "status": "active", "revokedAt": null, "createdAt": "2026-10-11T09:05:00.000Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" } }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000000007", "userId": "0199dfe1-0000-7000-8000-000000000008", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationRoleId": "0199dfe1-0000-7000-8000-000000000009", "joinedAt": "2026-10-11T08:00:00.000Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000000008", "email": "developer@example.com", "emailVerified": true, "metadata": { "version": 1, "name": "Example developer", "image": { "type": "emoji", "value": "πŸ‘€" } }, "lastLoginAt": "2026-10-11T08:55:00.000Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000000009", "key": "developer", "permissions": [ "wallet:read", "wallet:create", "session-key:read", "session-key:create", "api-key:create" ], "metadata": { "version": 1, "name": "Developer", "logo": { "type": "emoji", "value": "πŸ’»" }, "description": "Manage test accounts and session keys" }, "type": "custom", "systemRoleId": null } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000010", "chainId": "eip155:84532", "status": "installed", "authorization": { "version": 1, "entityId": 1, "signerAddress": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf", "permissions": [ { "type": "contract-access", "address": "0x2222222222222222222222222222222222222222" }, { "type": "native-token-transfer", "allowance": "1000000000000000" } ], "allowSignatures": false, "validAfter": 1791709200, "validUntil": 1794387600 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ] ```
## Options [#options] ### --wallet [#--wallet] - **Type:** `string` (account ID) - **Default:** no account filter Restrict the result to one account. Omit the flag to list all keys available to your credential. The result is not paginated. ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. Human output groups keys by account and shows networks whose installations are active within their permission window. JSON retains the complete records, including pending and expired installation details. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera sign > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/signatures/sign Sign a UTF-8 message or EIP-712 typed data with an account. Sign a UTF-8 message or EIP-712 typed data with an account. ## Usage [#usage] ```sh namera sign \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --session-key 0199dfe1-0000-7000-8000-000000000002 \ --network 'Base Sepolia' \ --type message \ --message 'Hello from Namera' ``` ## Output [#output]
```text Signature created -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Session key: Example session -> Type: Message -> Signature: 0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "signature": "0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b", "type": "message" } ```
The fixture signature illustrates the full output shape; use your returned signature for verification. ## Options [#options] ### --namespace [#--namespace] - **Type:** `evm | eip155` - **Required:** for non-interactive input flags Select the EVM network family. Both values resolve to the same namespace. This is not the chain ID; choose the network separately. ### --wallet [#--wallet] - **Type:** `string` (account ID) - **Required:** for non-interactive input flags Use an ID from `namera --output json wallet list`, not an Ethereum address. With input flags, the CLI reads the account to validate your selection. ### --network [#--network] - **Type:** network name, numeric chain ID, or CAIP-2 ID - **Required:** for non-interactive input flags For Base Sepolia, use `--network 'Base Sepolia'`, `--network 84532`, or `--network eip155:84532`. Names are case-insensitive. The supported networks are Ethereum, Sepolia, Base, Base Sepolia, Arbitrum One, Arbitrum Sepolia, OP Mainnet, and OP Sepolia. [Supported Networks](https://namera.ai/docs/sdk/supported-networks) lists their identifiers. ### --session-key [#--session-key] - **Type:** `string` (session-key ID) - **Required:** for non-interactive input flags Choose a key belonging to the selected account. Find IDs with `namera --output json session-key list --wallet `. Input flags require session-key read access to validate the key. Execution and signing also require a grant, an active installation on the chosen network, and matching permissions. ### --type [#--type] - **Type:** `message | typed-data` - **Required:** for non-interactive input flags Choose a UTF-8 message or an EIP-712 structured payload. There is no default. ### --message [#--message] - **Type:** `string` - **Required:** when `--type message` The exact UTF-8 message. Quote it to preserve spaces. Whitespace and letter case are part of the signed payload. Do not combine this with `--typed-data`. ### --typed-data [#--typed-data] - **Type:** JSON string - **Required:** when `--type typed-data` Supply `domain`, `types`, `primaryType`, and `message` following EIP-712. The domain identifies the application and can bind the signature to a chain and verifying contract. Use the same full object when verifying. Do not combine it with `--message`. ### --params [#--params] - **Type:** JSON string - **Required:** only when replacing individual input flags Pass the complete request as one JSON object. Use this for batch calls or scripts that already construct requests. JSON uses `eip155` for the namespace, CAIP-2 chain IDs, and decimal strings for bigint quantities. Do not combine it with individual transaction or signature input flags. It can be used with `--profile` and global output options. Supplying JSON skips the interactive selection and its extra account/session-key reads; authorization and request validation still apply. ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. The session's installed authority must allow signatures and any applicable API policies must allow the payload. Signing does not broadcast a transaction. Do not blindly repeat a signing command after losing its response; another attempt can consume another signature allowance. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # namera verify-signature > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/cli/reference/signatures/verify-signature Check an account signature against its original payload. Check an account signature against its original payload. ## Usage [#usage] ```sh namera verify-signature \ --namespace evm \ --wallet 0199dfe1-0000-7000-8000-000000000001 \ --network 'Base Sepolia' \ --type message \ --message 'Hello from Namera' \ --signature ``` ## Output [#output]
```text Signature valid -> Account: πŸ‘› Example account -> Network: Base Sepolia -> Type: Message ```
Example output uses fixture accounts and hashes, captured with the CLI's output formatters. Plain-text output is shown without terminal colors; your values and relative expiry dates will differ. With `--output json`:
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "valid": true, "type": "message" } ```
## Options [#options] ### --namespace [#--namespace] - **Type:** `evm | eip155` - **Required:** for non-interactive input flags Select the EVM network family. Both values resolve to the same namespace. This is not the chain ID; choose the network separately. ### --wallet [#--wallet] - **Type:** `string` (account ID) - **Required:** for non-interactive input flags Use an ID from `namera --output json wallet list`, not an Ethereum address. With input flags, the CLI reads the account to validate your selection. ### --network [#--network] - **Type:** network name, numeric chain ID, or CAIP-2 ID - **Required:** for non-interactive input flags For Base Sepolia, use `--network 'Base Sepolia'`, `--network 84532`, or `--network eip155:84532`. Names are case-insensitive. The supported networks are Ethereum, Sepolia, Base, Base Sepolia, Arbitrum One, Arbitrum Sepolia, OP Mainnet, and OP Sepolia. [Supported Networks](https://namera.ai/docs/sdk/supported-networks) lists their identifiers. ### --type [#--type] - **Type:** `message | typed-data` - **Required:** for non-interactive input flags Choose a UTF-8 message or an EIP-712 structured payload. There is no default. ### --message [#--message] - **Type:** `string` - **Required:** when `--type message` The exact UTF-8 message. Quote it to preserve spaces. Whitespace and letter case are part of the signed payload. Do not combine this with `--typed-data`. ### --typed-data [#--typed-data] - **Type:** JSON string - **Required:** when `--type typed-data` Supply `domain`, `types`, `primaryType`, and `message` following EIP-712. The domain identifies the application and can bind the signature to a chain and verifying contract. Use the same full object when verifying. Do not combine it with `--message`. ### --signature [#--signature] - **Type:** even-length `0x`-prefixed hex - **Required:** for non-interactive input flags Pass the complete signature returned by `namera sign`, with the same account, network, and original message or typed data. Do not strip its smart-account prefix. ### --params [#--params] - **Type:** JSON string - **Required:** only when replacing individual input flags Pass the complete request as one JSON object. Use this for batch calls or scripts that already construct requests. JSON uses `eip155` for the namespace, CAIP-2 chain IDs, and decimal strings for bigint quantities. Do not combine it with individual transaction or signature input flags. It can be used with `--profile` and global output options. Supplying JSON skips the interactive selection and its extra account/session-key reads; authorization and request validation still apply. ### --profile [#--profile] - **Type:** `string` - **Default:** `personal` Choose the saved CLI connection for this command. Pass the same name used at login. If `NAMERA_API_KEY` is set, ordinary API commands use that key instead of the profile's OAuth credentials. ```sh namera wallet list --profile work ``` The command also accepts [global options](https://namera.ai/docs/cli/reference/global-options): `--output pretty|json`, `--quiet`, and `--help`. There is no `--session-key` option. Verification establishes whether the account accepts the signature; it does not identify which session key signed. A successful command may return `valid: false`. Scripts must inspect this field rather than treating exit code zero as proof of validity. ## Errors [#errors] Failures exit nonzero and are written to stderr. With `--output json`, inspect `error.code` and `error.nextStep`. See [Output and Errors](https://namera.ai/docs/cli/output-and-errors). # Accounts > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/concepts/accounts Understand where assets live and how account ownership differs from delegated access. An **account** is a smart wallet that holds assets and executes transactions. It belongs to a [workspace](https://namera.ai/docs/concepts/organizations-and-workspaces) and has an owner that authorizes changes to its onchain permissions. Namera currently supports EVM smart accounts. The dashboard calls them **accounts**; the SDK and API use **wallets** for the same resource. ## Account Ownership [#account-ownership] The owner approves installing and removing session-key permissions. Agents use session keys instead of acting as that owner. Namera supports two account owner types: - **User-owned passkey:** you approve owner operations with your passkey. - **1Claw-managed:** owner signing uses a key managed through 1Claw, following an authorized user's approval in Namera. An account owner is not the same as a workspace's Owner role. Workspace roles control management access in Namera; account ownership controls the smart account's onchain authority. Signing in to Namera does not recover an account's owner passkey. Losing every copy can prevent owner approvals and onchain permission removal, and may lock funds in the account. ## Account Address and Account ID [#account-address-and-account-id] The **address** identifies the smart account on a network. Use it when receiving assets or looking up the account in a block explorer. The **account ID** identifies the account in Namera. SDK, CLI, and MCP requests use this ID to select it. The ID is not a blockchain address, and the account's display name is not a unique identifier. Always pair an address with the intended [network](https://namera.ai/docs/concepts/networks). Balances and activity on one network are separate from those on another. ## Delegated Access [#delegated-access] One account can have multiple [session keys](https://namera.ai/docs/concepts/session-keys), each with its own permissions and lifetime. For example, one key might allow payments to a specific recipient while another permits calls to a particular contract. Creating a key does not move assets into it. Assets remain in the account; the key gives a client limited authority to act on that account. An API key or connected app sees only the accounts reachable through its active session-key grants. Access to one key does not automatically reveal every account in the workspace. ## Separate Ownership from Key Storage [#separate-ownership-from-key-storage] Account ownership and session-key storage are independent. A passkey-owned account can use a managed session key, and a managed account can use a locally held session key. Neither arrangement makes the session key an account owner. Next, learn how [session keys](https://namera.ai/docs/concepts/session-keys) become usable and how their access ends. # Networks > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/concepts/networks Understand network-specific balances, permissions, and transaction status. An account operates on a specific blockchain network for each transaction. The network determines which balances, contracts, permissions, and activity apply to that operation. ## Supported Networks [#supported-networks] Namera supports these EVM mainnets and testnets: | Mainnet | Testnet | | ------------ | ---------------- | | Ethereum | Ethereum Sepolia | | Base | Base Sepolia | | Arbitrum One | Arbitrum Sepolia | | OP Mainnet | OP Sepolia | All eight use ETH as their native gas currency. Testnet ETH is separate from mainnet ETH. Use a testnet, such as Base Sepolia, when trying a new integration. For the exact identifiers used in code, see [Supported Networks in the SDK](https://namera.ai/docs/sdk/supported-networks). ## Balances Belong to a Network [#balances-belong-to-a-network] ETH held on Base is not an Ethereum balance. Selecting another network does not move or bridge assets, even if the account address looks the same. A token's symbol is not enough to identify it. Check its network and contract address, and check the recipient's network before funding an account or sending assets. A contract address on one network does not imply the same contract exists on another. ## Permissions Are Installed per Network [#permissions-are-installed-per-network] A session key needs owner-approved installation on every network where it will operate. An installation on Base does not authorize Ethereum or Base Sepolia. Each installation has its own status and approved authorization. The key can be active because one installation succeeded while another is still pending. Check the requested network, not only the key's overall status. Removing installed permissions is also network-specific. Revoking access through Namera starts the cutoff, but onchain removal must finish on each installed network. See [Session Keys](https://namera.ai/docs/concepts/session-keys#ending-access). ## Transactions and Gas [#transactions-and-gas] Gas pays for execution on the selected network. Sponsorship, when available, covers gas; it does not supply the ETH or tokens you intend to transfer. Self-funded execution requires sufficient native currency for gas as well as any amount being sent. Transactions have their own submission and confirmation state. Check activity and explorer links on the network used by the operation. If Namera pauses a supported network, new operations can be rejected while status checks remain available. A pause is not cancellation of an operation already signed or submitted. # Organizations and Workspaces > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/concepts/organizations-and-workspaces Understand how Namera groups accounts, members, and connected applications. A **workspace** groups your Namera accounts, session keys, members, client authorizations, and billing. The API calls this an **organization**. These are two names for the same boundary, not separate levels of a hierarchy. ## Your Active Workspace [#your-active-workspace] You can belong to multiple workspaces. Your dashboard session selects one active workspace at a time, and its pages show the resources you are allowed to access there. Switching workspaces changes that context. It does not move accounts, transfer funds, or give a connected application access to the newly selected workspace. If an expected account is missing, check the active workspace and your membership. ## Members and Roles [#members-and-roles] Your role determines which management actions you can perform in the workspace. Namera has built-in **Owner**, **Admin**, and **Member** roles. The Member role is read-oriented; management actions such as creating accounts or granting client access require the corresponding permissions. A person who can manage members cannot assign authority beyond their own. Account ownership remains separate: having a workspace role does not give you another person's owner passkey or replace an account's required owner approval. Membership and permissions are checked on subsequent requests. Losing workspace access does not transfer an account's assets or change its onchain owner. ## Connected Applications [#connected-applications] An API key, CLI connection, or MCP connection receives grants to selected session keys. It does not inherit the dashboard user's entire workspace role. For example, a workspace can contain accounts for several projects while one agent is authorized to use only a session key for a single account. Its accessible accounts and operations follow that grant and the key's permissions. Changing the active workspace in your browser does not change a saved CLI or MCP connection. Review that connection's authorization when changing its access. ## Workspace Owner and Account Owner [#workspace-owner-and-account-owner] The **workspace Owner** is a membership role in Namera. The **account owner** is the signing authority that approves onchain permission changes. One describes management access; the other describes control of a smart account. Keep these boundaries separate when planning team access. Removing a member or revoking an app connection is not the same operation as removing a session key's onchain permissions. Continue with [Accounts](https://namera.ai/docs/concepts/accounts) for account ownership or [Permissions and Policies](https://namera.ai/docs/concepts/permissions-and-policies) for delegated authority. # Permissions and Policies > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/concepts/permissions-and-policies Understand the checks that determine what a session key can do. Permissions define the authority you give a session key. API policies add restrictions to signature requests made through Namera. Transactions use onchain permissions. ## What Allows an Operation [#what-allows-an-operation] A client needs an active grant to an active session key. That key must have a confirmed installation on the requested network, and the operation must meet its permissions and every applicable API policy. A valid login is not enough. Neither is a funded account or an active key on a different network. ## Onchain Permissions [#onchain-permissions] The account owner approves these permissions, and the smart account's contracts enforce them. Depending on the configuration, they govern: - Which recipients, contracts, and functions the key can use. - Which tokens it can transfer or approve and the available allowances. - How much native currency it can send and the gas budget it can use. - When execution authority starts and expires. - Whether it has signature authority. These permissions belong to a specific network installation. Access on one network does not grant access on another. Choose the token or contract deployed on that network; the same name does not imply the same address. For example, a key intended to send **0.001 ETH** to one recipient needs both permission to call that recipient and a sufficient native-currency allowance. A gas budget is separate from the amount transferred. Unrestricted account access is broad execution authority. It is not equivalent to a narrow transfer permission and does not implicitly enable signatures. ## API Policies [#api-policies] API policies apply only to signing through Namera. They restrict signature types, typed-data domains, networks and time windows. Transaction limits live in the onchain installation, not a second API policy list. All configured signing policies must pass. Adding a more permissive policy does not override another policy’s denial. API policies cannot expand onchain authority. They also do not restrict an operation submitted outside Namera. Use onchain permissions for restrictions that must be enforced by the account itself. ## Amounts and Budgets [#amounts-and-budgets] Native spending measures the currency sent with calls. Token allowances apply to the specified token, and gas budgets cover execution costs. These are not interchangeable limits. Billing reserves execution and sponsorship allowance while an operation is pending. These usage holds are separate from onchain permission counters. ## Signature Permissions [#signature-permissions] Signing requires explicit onchain signature authority and an API policy allowing the requested message or typed-data signature. Transaction access alone does not permit signing. Typed-data policies can match a network, verifying contract, primary type, and domain. Matching those fields does not constrain amounts inside the message. A signature can authorize a later action even though signing it submits no transaction at that moment. Onchain transaction spending limits and execution expiry do not constrain onchain signature authority. Remove the installed authority onchain to end it; revoking Namera access alone only blocks requests through Namera. ## Simulation and Confirmation [#simulation-and-confirmation] Simulation previews the calls using the installed session without submitting the transaction. It is not a promise that execution will succeed: balances, budgets, and network state can change. A successful submission is also not confirmation. Use the returned submission ID to follow its status rather than repeating the operation. # Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/concepts/session-keys Give an application or agent bounded access to one account. A **session key** is a signing key with permissions attached to one account. It lets an application or agent act without receiving the account owner's key. Each session key has its own allowed actions, network installations, and execution lifetime. Creating separate keys for different tasks makes their permissions and access easier to manage independently. ## Three Different Kinds of Access [#three-different-kinds-of-access] | Item | Purpose | | -------------------------------------- | ------------------------------------------------------------------------------------ | | Account owner | Approves installing or removing onchain authority. | | Session key | Signs operations within the authority installed for it. | | API key or connected-app authorization | Authenticates a client and grants it access to selected session keys through Namera. | An API key is not a session private key. Authorizing an app does not install permissions onchain, and installing a session key does not authorize every app to use it. ## Registration and Network Approval [#registration-and-network-approval] A newly created session key starts **pending**. Its permissions must be approved by the account owner and installed on a network before it can be used there. The key becomes **active** after an installation is confirmed. That status does not mean every requested network is ready: each network has its own installation and validity period. A pending approval on Base is not made usable by a confirmed installation on Ethereum. Configure each network separately during creation. One key can have a 100 USDC lifetime allowance on Ethereum and a 200 USDC allowance on Base, using each network's token address. The allowances are independent, not a shared 300 USDC budget. Lifetimes and signature authority can also differ by network. The client also needs an active grant to the key. Namera evaluates the selected key's complete permissions for each operation; it does not combine partial permissions from different keys to make an action pass. ## Where the Signing Key Lives [#where-the-signing-key-lives] A local session key signs on the machine where it was imported. A managed session key signs through 1Claw. Both use the same delegated-access model and require the appropriate network installation and Namera authorization. Follow any encrypted import and backup instructions provided during creation. Importing a key alone does not approve its network permissions or connect an app. Do not share a private key or export passphrase with an agent. ## Changing Permissions [#changing-permissions] A session key's permission configuration is fixed when it is created. To use a different permission set, create a replacement key and authorize the intended clients to use it. Revoke the old key when it is no longer needed. ## Ending Access [#ending-access] Revoking a session key cuts off its grants through Namera immediately and starts revocation. Any installed onchain permissions still require owner-approved removal on each network. The key remains **revoking** while those operations are unresolved; **revoked** means the removal lifecycle has finished. Execution expiry and signature authority are different. Expiry does not remove onchain message-signing authority. See [Permissions and Policies](https://namera.ai/docs/concepts/permissions-and-policies#signature-permissions) before enabling signatures. Revocation is not a way to cancel a transaction that has already been submitted. Track that submission separately. # Getting Started > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/getting-started Create an account, give a session key limited access, and connect your first client. Set up an account and a session key, then connect an agent, terminal, or application. This walkthrough starts on **Base Sepolia**, a test network, and checks access before sending any transaction. ## Open Your Workspace [#open-your-workspace] Sign in to the [Namera dashboard](https://dashboard.namera.ai) and check the workspace selected in the sidebar. Your accounts and session keys belong to that workspace. You need permission to create accounts and session keys and authorize a client. If those actions are unavailable, ask your workspace owner or admin for access. ## Create an Account [#create-an-account] Open **Accounts** and select **Create account**. Enter a name you can recognize, such as `Test account`, and choose an available ownership option: - **User-owned passkey:** complete the passkey prompt to create the account's owner credential. - **1Claw Managed:** create an account whose owner signing is managed through 1Claw. After creation, open the account and confirm its name and address. You can also use an existing account in this workspace. If you choose a passkey-owned account, keep access to that passkey. Your Namera login cannot restore it, and you need it to approve onchain permission changes. ## Create a Session Key [#create-a-session-key] Open **Session Keys** and select **Create session key**. Choose your account and give the key a task-specific name, such as `Test transfers`. For a small test transfer, configure: - **Network:** Base Sepolia. - **Recipient:** a separate address you control, permitted as a call target. - **Native spending limit:** 0.001 ETH. - **Expiry:** a future date that covers your test. Leave signature authority and unrestricted account access disabled for this transfer-only key. Review the final permission summary before creating it. See [Permissions and Policies](https://namera.ai/docs/concepts/permissions-and-policies) if you are unsure what a restriction controls. If creation provides an encrypted key export, complete the displayed encryption and CLI import instructions on the machine that will run your client. Save the encrypted backup and its passphrase securely before leaving the page. Never paste the private key or passphrase into an agent conversation. ## Approve Network Access [#approve-network-access] In **Enable networks**, review the Base Sepolia installation and select **Approve**. Complete the owner approval required by your account. Wait for the installation to be confirmed. A registered key is initially pending; it is not ready simply because creation succeeded. Before continuing, confirm that the key is active and Base Sepolia is enabled. If you skipped network approval during creation, return to the session key's overview to finish it. Approval on another network does not enable Base Sepolia. ## Connect Your Client [#connect-your-client] Choose how you want to use the account: | Client | Next step | | ---------------------- | -------------------------------------------------------------------------------------------------------------- | | AI agent | Follow the [MCP guide for your client](https://namera.ai/docs/mcp/clients), then approve its browser connection. | | Terminal | Follow [CLI Getting Started](https://namera.ai/docs/cli/getting-started) and sign in with `namera login`. | | TypeScript application | Follow [SDK Getting Started](https://namera.ai/docs/sdk/getting-started) and create an API key with access to this session key. | Grant the client access only to the session key you prepared. A dashboard login does not automatically authorize an API key, CLI installation, or MCP connection. ## Check Access First [#check-access-first] Use your client to list accounts and session keys. For an agent, ask: > List my Namera accounts and inspect the Test transfers session key. Confirm > its Base Sepolia access, recipient permission, spending limit, and expiry. > Do not submit transactions or sign anything. Confirm that the returned account and permissions match what you configured. An empty list usually means the connection has no active grant to the key; check the authorized keys and installation status in the dashboard. You do not need to fund the account to perform these read-only checks. ## Try a Test Transaction [#try-a-test-transaction] When you are ready to transfer, fund the account address with **0.001 Base Sepolia test ETH**. Use sponsored gas if available; self-funded gas requires additional test ETH and the client's gas-limit configuration. Continue with the [SDK](https://namera.ai/docs/sdk/getting-started) or [CLI](https://namera.ai/docs/cli/getting-started) walkthrough, or ask your connected agent to simulate the transfer and explain the result before you approve execution. Check the resulting submission until it is confirmed or failed. Do not repeat the transfer just to check progress. After testing, revoke access you no longer need; [session-key revocation](https://namera.ai/docs/concepts/session-keys#ending-access) also requires removal of any installed onchain permissions. # Introduction > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs Welcome to Namera Documentation Namera is programmable smart wallet infrastructure for agents, applications, and developers who need fine-grained control over onchain execution. Instead of giving an agent unrestricted access to a wallet, you give it a session key with explicit permissions. You decide which networks and contracts it can use, what it can do, and how much it can spend. Account ownership stays separate from the access you give each integration. ## How to Use These Docs [#how-to-use-these-docs] Start with [Why Namera](https://namera.ai/docs/why-namera) for the reasoning behind permissioned wallet access, or follow [Getting Started](https://namera.ai/docs/getting-started) to set up your first account and client. Read [Accounts](https://namera.ai/docs/concepts/accounts), [Session Keys](https://namera.ai/docs/concepts/session-keys), and [Permissions and Policies](https://namera.ai/docs/concepts/permissions-and-policies) for the core concepts. Then choose the section that fits how you want to work: - [SDK](https://namera.ai/docs/sdk) for integrating wallet execution and signing into a TypeScript application. - [CLI](https://namera.ai/docs/cli) for working with accounts and session keys from your terminal. - [MCP](https://namera.ai/docs/mcp) for giving compatible agent clients access to Namera's wallet tools. These clients use the same permission model. Access is scoped to the session keys you authorize, rather than every account in your workspace. Use the section picker to switch between SDK, CLI, and MCP, or search for a page directly. On larger screens, the table of contents on the right lets you jump between headings within a page. ## Docs for LLMs [#docs-for-llms] We support the `llms.txt` convention so language models and the applications that use them can read the documentation as Markdown. - [llms.txt](https://namera.ai/llms.txt): an index of documentation and other public site content. - [llms-full.txt](https://namera.ai/llms-full.txt): all published documentation in one Markdown file. You can also read any documentation page as Markdown by appending `.md` to its URL, such as [/docs.md](https://namera.ai/docs.md). The **Copy Markdown** and **Open** controls at the top of each page provide the same content. # Authentication > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/authentication Authorize a client, check its connection, and revoke access. Each MCP connection uses browser authorization. You choose the session keys and access it receives. Credentials stay in your OS keyring, not in the client config. ## Connect [#connect] Use the profile from your client's `mcp serve` arguments. For example: ```sh namera mcp login --profile codex ``` Open the printed authorization URL if the browser does not open automatically. Approve only the access this client needs. You can also start from the client: the first authenticated tool call opens consent when no usable connection exists. After approval, retry that request. Simply seeing tools in the client does not mean you have signed in. Ordinary `namera login`, your client's own account login, and `NAMERA_API_KEY` do not authorize the Namera MCP connection. ## Check the Connection [#check-the-connection] ```sh namera mcp status --profile codex ``` Status reports the saved connection on this machine. It is not a live check of server-side access. A revoked grant can still appear locally connected until a tool request checks it. If login is required, run `namera mcp login` with that profile again. Saved credentials normally allow the client to reconnect without a new browser approval. ## Change Access [#change-access] Manage the connection and session-key permissions in the dashboard. If you need to select a different set of keys, authorize the same profile again. A client cannot expand its own permissions through a tool call. ## Disconnect [#disconnect] ```sh namera mcp logout --profile codex ``` Logout disables the local credentials and requests revocation of the MCP authorization. If revocation fails, follow the error's instructions to revoke the connection in the dashboard. Imported session keys are not deleted. Also remove or disable the server in your client. Removing its configuration alone does not revoke the authorization. # Claude Code > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/claude-code Add Namera to Claude Code using a user-scoped stdio connection. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] With Claude Code installed: ```sh claude mcp add --transport stdio --scope user namera -- namera mcp serve --profile claude-code ``` User scope makes the registration available across your projects. To limit it to the current project instead, use `--scope local`. The `--` separates Claude's options from Namera's launch command. See [Claude Code's MCP documentation](https://code.claude.com/docs/en/mcp). ## Authorize [#authorize] ```sh namera mcp login --profile claude-code namera mcp status --profile claude-code ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Start Claude Code and run `/mcp` to check the connection. If you added the server during an existing session, restart that session before testing. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile claude-code ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Claude Desktop > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/claude-desktop Configure Namera as a local server in the Claude desktop app. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] In Claude Desktop, open **Settings β†’ Developer β†’ Edit Config**. Add Namera to `claude_desktop_config.json`: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "claude-desktop"] } } } ``` Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). Use the desktop app's local-server configuration, not a remote connector URL. See the [official local-server setup](https://modelcontextprotocol.io/docs/develop/connect-local-servers) for the configuration location on your OS. ## Authorize [#authorize] ```sh namera mcp login --profile claude-desktop namera mcp status --profile claude-desktop ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Fully quit and reopen Claude Desktop after saving the config. Check that Namera appears among the available local tools. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile claude-desktop ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Cline > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/cline Add Namera to the Cline extension's MCP configuration. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] In Cline, open **MCP Servers β†’ Configure β†’ Configure MCP Servers**. Add this entry to the settings JSON opened by the extension: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "cline"] } } } ``` Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). Use Cline's configuration, not VS Code's `.vscode/mcp.json`; these configure different clients. See [Cline's MCP documentation](https://github.com/cline/cline/blob/main/docs/mcp/mcp-overview.mdx). ## Authorize [#authorize] ```sh namera mcp login --profile cline namera mcp status --profile cline ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Check Namera in Cline's MCP Servers panel. Reconnect the server if needed, then start a task with MCP tool access enabled. Do not add execution or signing to an auto-approve list just to get the first read request working. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile cline ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Codex > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/codex Connect Codex to Namera with a local MCP server. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] With Codex CLI installed, register the server: ```sh codex mcp add namera -- namera mcp serve --profile codex ``` Alternatively, add this to `~/.codex/config.toml`. Use one method, not both: ```toml [mcp_servers.namera] command = "namera" args = ["mcp", "serve", "--profile", "codex"] ``` Codex uses this configuration for its local clients. In the IDE extension, you can also add a **STDIO** server through **MCP servers** in the gear menu. See the [official Codex MCP setup](https://developers.openai.com/codex/mcp). ## Authorize [#authorize] ```sh namera mcp login --profile codex namera mcp status --profile codex ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. Use Namera's login command, not `codex mcp login namera`: this local server owns its browser authorization flow. ## Use Namera [#use-namera] Start a new Codex session. Run `/mcp` in the CLI to inspect active servers, or `codex mcp list` from your terminal to check the saved registration. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile codex ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Cursor > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/cursor Make Namera available to Cursor Agent through a local MCP connection. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] Add this to `~/.cursor/mcp.json` for your user, or `.cursor/mcp.json` in a project for project-specific configuration: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "cursor"] } } } ``` Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). Project configuration takes precedence when both files define `namera`. This is a local Cursor Agent setup, not a cloud-agent endpoint. See [Cursor's MCP configuration](https://cursor.com/help/customization/mcp). ## Authorize [#authorize] ```sh namera mcp login --profile cursor namera mcp status --profile cursor ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Open Cursor's MCP settings and check that Namera is enabled. Restart its server or reload Cursor if the new tools do not appear. Use Agent mode for tool calls. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile cursor ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Gemini CLI > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/gemini-cli Add Namera to Gemini CLI's local MCP servers. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] With Gemini CLI installed, add this to `~/.gemini/settings.json` for your user, or `.gemini/settings.json` for the current project: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "gemini"], "trust": false } } } ``` `trust: false` keeps tool approval prompts instead of trusting all calls from the server. See [Gemini CLI's MCP setup](https://geminicli.com/docs/tools/mcp-server/). Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). ## Authorize [#authorize] ```sh namera mcp login --profile gemini namera mcp status --profile gemini ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Start a new Gemini CLI session and run `/mcp` to inspect the connected servers and available tools. If Namera is excluded by your MCP settings, enable it before testing the connection. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile gemini ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Grok > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/grok Understand the transport requirement before connecting Grok to Namera. Grok's documented MCP connectors require a remote server URL. Namera currently provides a local stdio server, so there is no Namera MCP URL to enter in Grok. ## Why a URL Does Not Work [#why-a-url-does-not-work] Grok connects to a server over the network. It cannot launch `namera mcp serve` on your computer through that URL-based connector. The [xAI remote MCP API](https://docs.x.ai/developers/tools/remote-mcp) likewise requires a server URL. The Namera API address is not an MCP endpoint. A tunnel alone also does not convert a stdio process into an HTTP server; Grok's [tunneling instructions](https://docs.x.ai/grok/connectors/custom-mcp-tunneling) assume you already have a network-listening server. ## Use a Local Client [#use-a-local-client] Connect through [Cursor](https://namera.ai/docs/mcp/clients/cursor), [OpenCode](https://namera.ai/docs/mcp/clients/opencode), or another [local MCP client](https://namera.ai/docs/mcp/clients). If that client offers a Grok model with tool support, it is the client, not Grok's hosted connector, that launches Namera. Model availability depends on the client and your account. These docs do not provide an unauthenticated HTTP bridge or instructions to expose a locally authorized wallet connection to the internet. # Overview > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients Find the connection instructions for your AI client. Install [Namera](https://namera.ai/docs/mcp/installation), prepare your [account and session key](https://namera.ai/docs/mcp/getting-started#prepare-your-account), then follow your client's guide. Each configuration uses a separate named connection. ## Coding Agents [#coding-agents] - [Codex](https://namera.ai/docs/mcp/clients/codex) - [Claude Code](https://namera.ai/docs/mcp/clients/claude-code) - [Gemini CLI](https://namera.ai/docs/mcp/clients/gemini-cli) - [OpenCode](https://namera.ai/docs/mcp/clients/opencode) ## Editors [#editors] - [Cursor](https://namera.ai/docs/mcp/clients/cursor) - [VS Code](https://namera.ai/docs/mcp/clients/vscode) - [Cline](https://namera.ai/docs/mcp/clients/cline) - [Windsurf / Devin Desktop](https://namera.ai/docs/mcp/clients/windsurf) - [Kiro](https://namera.ai/docs/mcp/clients/kiro) - [Zed](https://namera.ai/docs/mcp/clients/zed) ## Desktop and Personal Agents [#desktop-and-personal-agents] - [Claude Desktop](https://namera.ai/docs/mcp/clients/claude-desktop) - [OpenClaw](https://namera.ai/docs/mcp/clients/openclaw) ## Other Connections [#other-connections] [Grok](https://namera.ai/docs/mcp/clients/grok) currently requires a remote endpoint for its documented MCP connector, so it cannot connect directly to Namera's local server. For a client not listed here, see [Other Clients](https://namera.ai/docs/mcp/clients/other-clients). These instructions use the clients' documented local MCP configuration formats. Tool approval controls and availability can vary by version or organization policy. Check each page's upstream documentation if its settings have moved. # Kiro > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/kiro Connect the Kiro IDE to Namera through a local MCP server. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] In the Kiro IDE command palette, run **Kiro: Open user MCP config (JSON)** for all workspaces, or **Kiro: Open workspace MCP config (JSON)** for the current workspace. Add this to the file it opens: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "kiro"], "disabled": false, "autoApprove": [] } } } ``` Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). IDE configs live at `~/.kiro/settings/mcp.json` or `.kiro/settings/mcp.json`. Save the file to reconnect servers. Keep `autoApprove` empty so this entry does not automatically approve tools. See [Kiro's MCP configuration](https://kiro.dev/docs/mcp/configuration/). ## Authorize [#authorize] ```sh namera mcp login --profile kiro namera mcp status --profile kiro ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Enable MCP support in Kiro's settings if it is disabled. Check the Namera server in the MCP panel, then open a new chat with the agent. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile kiro ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # OpenClaw > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/openclaw Connect Namera to agents running through your OpenClaw Gateway. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. For OpenClaw, that machine is the **Gateway host**, which may be different from the device where you send messages. Its OS user needs access to Namera's keyring and any imported keys. A container without a usable keyring is not sufficient. ## Add Namera [#add-namera] In the Control UI, open **Settings β†’ MCP β†’ Add server**. Enter: | Field | Value | | --------- | --------------------------------------- | | Name | `namera` | | Transport | Stdio | | Command | `namera` | | Arguments | `mcp`, `serve`, `--profile`, `openclaw` | Save the server. If the form accepts one command line, enter `namera mcp serve --profile openclaw`. Server definitions live under `mcp.servers`; do not paste another client's `mcpServers` wrapper into OpenClaw's config. See [OpenClaw's MCP setup](https://docs.openclaw.ai/tools/mcp). ## Authorize [#authorize] On the Gateway host, as the user that runs it: ```sh namera mcp login --profile openclaw namera mcp status --profile openclaw ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. Browser approval must reach the login process's loopback callback. If the Gateway runs on a remote host without browser access, resolve that environment requirement before using Namera; authorizing only on your laptop will not connect it. ## Use Namera [#use-namera] Check server discovery on the Gateway host: ```sh openclaw mcp doctor namera --probe ``` Make Namera available to the intended agent and session through OpenClaw's tool policy. Connecting a server does not bypass those controls. Start with a private conversation, not a shared channel whose participants should not control the account. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile openclaw ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # OpenCode > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/opencode Configure Namera as a local MCP server in OpenCode. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] Add this to your project's `opencode.json`: ```json { "$schema": "https://opencode.ai/config.json", "mcp": { "namera": { "type": "local", "command": ["namera", "mcp", "serve", "--profile", "opencode"], "enabled": true } } } ``` OpenCode uses **`mcp`** and a single command array, not a separate `args` field. See [OpenCode's MCP configuration](https://opencode.ai/docs/mcp-servers/). Merge the entry with existing settings. If needed, replace the first command array element with Namera's [absolute path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). ## Authorize [#authorize] ```sh namera mcp login --profile opencode namera mcp status --profile opencode ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Start OpenCode from the project containing the configuration. Make sure the selected agent's tool settings do not disable Namera's tools, then open a new conversation. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile opencode ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Other Clients > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/other-clients Connect any client that can launch a local stdio MCP server. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Check Local Server Support [#check-local-server-support] Your client must support **stdio** servers with a command and arguments. If it only accepts a remote URL, it cannot connect directly to the current Namera MCP server. Do not use the Namera API address as an MCP endpoint. ## Configure the Server [#configure-the-server] Use these values in your client's local-server settings: | Field | Value | | --------- | ------------------------------------ | | Name | `namera` | | Transport | stdio | | Command | `namera` | | Arguments | `mcp`, `serve`, `--profile`, `agent` | For clients that use a `mcpServers` JSON object: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "agent"] } } } ``` The wrapper and config location depend on the client. VS Code, Zed, and OpenCode use different formats; follow their [specific guides](https://namera.ai/docs/mcp/clients). Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). The client starts and stops the process. Do not run a second server manually, background the command, or redirect its stdout: stdio carries the MCP protocol. ## Authorize [#authorize] ```sh namera mcp login --profile agent namera mcp status --profile agent ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. Choose a different profile for each additional client and use it consistently in the launch, login, status, and logout commands. ## Use Namera [#use-namera] Restart the client's server connection and check that its tools are available. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile agent ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # VS Code > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/vscode Connect Namera to agent chat in Visual Studio Code. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] In your workspace, create or edit `.vscode/mcp.json`: ```json { "servers": { "namera": { "type": "stdio", "command": "namera", "args": ["mcp", "serve", "--profile", "vscode"] } } } ``` VS Code uses **`servers`**, not `mcpServers`, in this file. Use the editor's **Start** control above the server entry and approve server trust when prompted. See [VS Code's MCP configuration](https://code.visualstudio.com/docs/agents/reference/mcp-configuration). Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). ## Authorize [#authorize] ```sh namera mcp login --profile vscode namera mcp status --profile vscode ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. If you use a remote workspace, confirm where VS Code launches the server. Namera must have its installation, keyring, and browser-login access in that environment. Start with a local workspace if those are unavailable remotely. ## Use Namera [#use-namera] Open agent chat and enable Namera's tools in the tools picker. MCP access may be restricted by your organization's VS Code policies. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile vscode ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Windsurf / Devin Desktop > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/windsurf Connect Namera to the Cascade agent's local MCP configuration. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera to Cascade [#add-namera-to-cascade] This setup is for **Cascade**. The current Windsurf documentation redirects to Devin Desktop and distinguishes Cascade from the newer Devin Local agent, which uses a different configuration. See the [current Cascade MCP documentation](https://docs.devin.ai/desktop/cascade/mcp). In Cascade's **…** actions menu, open the MCP configuration file. Add: ```json { "mcpServers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "windsurf"] } } } ``` Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). Open the file through the app so you edit the configuration used by your installed version, rather than assuming an older Windsurf directory is still active. ## Authorize [#authorize] ```sh namera mcp login --profile windsurf namera mcp status --profile windsurf ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Enable Namera in Cascade's MCP controls and start a new conversation. If tools are missing, check the server toggle and any organization-level MCP restrictions. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile windsurf ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Zed > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/clients/zed Add Namera to Zed's Agent Panel as a context server. Install [Namera](https://namera.ai/docs/mcp/installation) and complete [account setup](https://namera.ai/docs/mcp/getting-started#prepare-your-account) on the machine that will run the client. Make sure its process can find both `namera` and Node.js. ## Add Namera [#add-namera] Open Zed's settings JSON and add a `context_servers` entry: ```json { "context_servers": { "namera": { "command": "namera", "args": ["mcp", "serve", "--profile", "zed"] } } } ``` Merge this entry into your existing configuration without removing other servers or settings. If `namera` cannot be found, use its [absolute executable path](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). Zed calls these **context servers**. Use `context_servers`, not `mcpServers`. See [Zed's MCP documentation](https://zed.dev/docs/ai/mcp). ## Authorize [#authorize] ```sh namera mcp login --profile zed namera mcp status --profile zed ``` Approve the connection in your browser and select the active session keys it may use. Run these commands as the same OS user that runs the client. Namera saves the connection in your OS keyring; no API key belongs in the client config. ## Use Namera [#use-namera] Open **Settings β†’ AI β†’ MCP Servers** and check that Namera is active. In the Agent Panel, select a profile that includes its tools. Keep the tool permission policy on confirmation rather than allowing every tool automatically. Ask in a new conversation: > Use Namera to list my accounts and session keys. Summarize their networks and > permissions. Do not submit a transaction or sign a message. Allow the read tools if prompted. If Namera requests browser authorization, complete it and retry the read request. An empty result means no resources were returned for this connection; do not ask the agent to invent account details. Keep tool confirmations enabled for execution and signing where supported. See [Permissions and Limits](https://namera.ai/docs/mcp/permissions) before granting broader access. ## Disconnect [#disconnect] ```sh namera mcp logout --profile zed ``` Also remove or disable the `namera` server in the client to stop it launching. Logout revokes the MCP connection without deleting imported keys. If revocation fails, revoke the connection in the dashboard as instructed by the error. # Getting Started > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/getting-started Prepare an account, connect your client, and make your first read-only request. ## Install Namera [#install-namera] ```sh npm install -g @namera-ai/cli ``` Use Node.js 24.14+ and an unlocked OS keyring. See [Installation](https://namera.ai/docs/mcp/installation) for other package managers. ## Prepare Your Account [#prepare-your-account] In the [Namera dashboard](https://dashboard.namera.ai): 1. Create or choose an account. 2. Create a session key with the permissions you want the agent to have. 3. If the dashboard provides an encrypted import command, run it on the machine that will run your MCP client. Enter the export passphrase privately. 4. Approve the key's installation on your chosen network and wait until it is active. You select active session keys during connection approval. You do not need to fund the account to list it or inspect its permissions. ## Connect Your Client [#connect-your-client] Choose a [client setup guide](https://namera.ai/docs/mcp/clients). Each guide provides its exact command or configuration, plus a named profile for the connection. For example, with Codex installed: ```sh codex mcp add namera -- namera mcp serve --profile codex namera mcp login --profile codex ``` Approve the connection in your browser and select the session keys it can use. Use the same profile name shown in your client's configuration. ## Make Your First Request [#make-your-first-request] Start a new conversation in the client and ask: > Use Namera to list my accounts and their session keys. Summarize the available > networks and permissions. Do not submit transactions or sign anything. Allow the read tools if the client asks. The answer depends on the accounts and keys you authorized; it should come from Namera tools, not the agent's memory. If you skipped login, the first authenticated tool call starts browser consent. Approve it, then ask the agent to retry the read request. ## Manage Access [#manage-access] Change permissions in the dashboard. To disconnect the example Codex profile: ```sh namera mcp logout --profile codex ``` Remove the server from your client's configuration separately to stop it from launching. See [Authentication](https://namera.ai/docs/mcp/authentication) for connection lifecycle and [Troubleshooting](https://namera.ai/docs/mcp/troubleshooting) if a tool fails. # Overview > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp Give your AI client access to Namera accounts within the permissions you choose. Namera connects your AI client to accounts, session keys, transactions, and signatures through the Model Context Protocol (MCP). You approve access in your browser. The agent discovers the available tools and uses them on your behalf. ## What You Can Ask [#what-you-can-ask] ### Inspect Your Accounts [#inspect-your-accounts] > List my Namera accounts and show which networks each session key can use. ### Check Activity [#check-activity] > Show the recent confirmed transactions for my Namera account. ### Prepare an Action [#prepare-an-action] > Check whether my Namera session key allows the transfer I describe. Simulate > it, explain the result, and wait for my approval before submitting anything. Your session key's permissions remain the limit, regardless of what you ask the agent to do. Prompts guide the agent; they do not grant or restrict server-side authority. Configure that in the [dashboard](https://dashboard.namera.ai). ## How It Connects [#how-it-connects] The Namera CLI includes a local MCP server. Your client starts it automatically and communicates over **stdio**. You do not run a background daemon or paste an API key into a client configuration. The process runs on your machine and calls the Namera API. It is not an offline wallet, and there is no hosted Namera MCP URL to add to cloud-only clients. Start with [Installation](https://namera.ai/docs/mcp/installation), then [choose your client](https://namera.ai/docs/mcp/clients). # Installation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/installation Install the local MCP server included in the Namera CLI. ## Requirements [#requirements] Use **Node.js 24.14+**, an accessible OS keyring, and a client that can launch local stdio MCP servers. Install Namera on the machine where that client runs. On Linux, use a persistent Secret Service session so saved credentials and imported keys remain available after reboot. ## Install [#install] ```sh npm install -g @namera-ai/cli ``` ```sh pnpm add -g @namera-ai/cli ``` ```sh yarn global add @namera-ai/cli ``` ```sh bun add -g @namera-ai/cli ``` Use one command. The Yarn command requires Yarn Classic; with modern Yarn, use npm or pnpm for the global install. Bun installs the package, but the executable still runs on Node.js. ```sh namera --version ``` Continue to [Getting Started](https://namera.ai/docs/mcp/getting-started) or go directly to [your client's setup page](https://namera.ai/docs/mcp/clients). ## Update [#update] ```sh npm install -g @namera-ai/cli@latest ``` Restart the MCP server in your client after updating. Saved connections and imported keys are retained. # Permissions and Limits > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/permissions Decide what an agent can access before connecting it. Namera checks both the connection's access and the selected session key's permissions. A successful client connection does not give the agent unrestricted access to your account. ## Choose Connection Access [#choose-connection-access] Browser consent separates reading accounts, keys, and history from executing transactions and signing. Simulation also requires execution access. Select only the active session keys this client needs. For an inspection-only client, grant read access without execute/sign access. Hiding a tool in the client's UI is useful, but does not replace limiting its Namera authorization. ## Set Session-Key Permissions [#set-session-key-permissions] In the dashboard, configure the allowed networks, recipients or contracts, amount limits, and expiry for the intended work. The session key must be active and installed on the requested network. Message signing requires its own permission; permission to transfer does not imply permission to sign. The agent can inspect these permissions. It cannot create accounts, install session keys, or approve a wider permission set through Namera's MCP tools. ## Keep Approval in the Client [#keep-approval-in-the-client] Review your client's tool approval settings before allowing asset movement. Keep confirmations enabled for execution and signing where the client supports them. A prompt such as β€œask me first” is not a substitute for enforced limits. Do not paste a private key, encrypted export, passphrase, or API key into a chat. Complete any dashboard-provided import in your terminal. ## Gas Limits [#gas-limits] The default server configuration permits sponsored executions only, subject to Namera's sponsorship checks. To permit self-funded gas, set a ceiling in the server arguments yourself: ```sh namera mcp serve --profile agent --max-gas-cost-wei 1000000000000000 ``` That ceiling is **0.001 ETH** in wei. It limits gas cost, not the transfer amount. Add the flag to the command your client launches; do not start a second server in a terminal. Agents cannot raise this ceiling through tools. ## Submission Is Not Confirmation [#submission-is-not-confirmation] Ask the agent to track a submission until it is confirmed or failed. If the response is interrupted, check the known submission ID before requesting another execution. Repeating an execution can move assets twice. # Profiles and Configuration > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/profiles-and-configuration Separate client connections and configure where the MCP server runs. ## Give Each Client a Profile [#give-each-client-a-profile] Use a distinct profile such as `codex`, `cursor`, or `openclaw`. The profile and API origin together identify the saved MCP connection. ```sh namera mcp login --profile cursor namera mcp status --profile cursor ``` The client's launch arguments must match: ```json { "command": "namera", "args": ["mcp", "serve", "--profile", "cursor"] } ``` This is the server entry, not a complete client config. Each [client guide](https://namera.ai/docs/mcp/clients) shows its required wrapper. If omitted, the MCP profile is `default`. Profiles keep connections separate; they are not a security boundary between processes running as the same OS user. ## Use the Same Machine and OS User [#use-the-same-machine-and-os-user] Run login and the MCP server as the same OS user, with access to the same keyring and any imported keys. A login on your laptop does not authorize a server running inside a container, remote workspace, or another user's background service. For GUI clients, `namera` and Node.js must be available in the environment used to launch the server. If the executable is not found, see [Troubleshooting](https://namera.ai/docs/mcp/troubleshooting#the-client-cannot-find-namera). ## Use a Different API Origin [#use-a-different-api-origin] For a local Namera development server: ```sh namera mcp login --profile dev --host http://localhost:8080 namera mcp status --profile dev --host http://localhost:8080 ``` Set matching server arguments: ```json { "command": "namera", "args": ["mcp", "serve", "--profile", "dev", "--host", "http://localhost:8080"] } ``` Use the same `--host` for logout. MCP commands default to `https://api.namera.ai` and do not use `NAMERA_API_URL` to select a host. The host is an API origin, not an MCP endpoint. Non-loopback origins must use HTTPS. See the CLI's [server options](https://namera.ai/docs/cli/reference/mcp/serve) for the complete launch-command details. # Troubleshooting > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/mcp/troubleshooting Resolve startup, browser approval, keyring, and access problems. ## The Client Cannot Find Namera [#the-client-cannot-find-namera] Check the installation in a terminal: ```sh node --version namera --version ``` Use Node.js 24.14+. If the terminal works but the app does not, find the executable: ```sh command -v namera ``` On Windows, use `where.exe namera`. Replace the client's `command` with the returned absolute executable path. If Windows returns a `.cmd` shim that your client cannot launch directly, use that client's documented Windows command launcher. Node.js must also be on the child process's PATH. Restart the client after changing its environment. ## The Client Asks for a Server URL [#the-client-asks-for-a-server-url] Choose its local command or stdio option. Namera does not provide a hosted MCP endpoint. An API URL is not an MCP URL. URL-only clients cannot connect directly; see [Other Clients](https://namera.ai/docs/mcp/clients/other-clients). ## Tools Appear, but Login Is Required [#tools-appear-but-login-is-required] Tool discovery does not require login. Authorize the exact profile configured in the server arguments: ```sh namera mcp login --profile agent namera mcp status --profile agent ``` Replace `agent` with your profile. Use the same custom `--host`, if configured. Retry the original read request after approval. Do not use ordinary `namera login` or add an API key to the MCP config. ## Browser Approval Does Not Finish [#browser-approval-does-not-finish] Run manual login on the machine that starts the MCP server. Open the URL printed by the command and complete approval before it expires. For remote environments, the browser must be able to reach the login process's loopback callback; a browser on a different machine may not be able to complete it. Start a fresh login if the previous attempt expired or was cancelled. ## Credentials or Keys Are Unavailable [#credentials-or-keys-are-unavailable] Unlock the OS keyring and run the client as the same OS user used for login and import. On Linux, check that a persistent Secret Service is available to that process. There is no plaintext credential fallback. Do not delete the key store to fix an error. If the dashboard provided a key import, complete it on this machine. Follow the [import instructions](https://namera.ai/docs/cli/reference/session-keys/session-key-import) if you need to restore from your encrypted backup. ## No Accounts or Session Keys Are Returned [#no-accounts-or-session-keys-are-returned] Check the connection's selected keys in the dashboard. Confirm the key is active, its network installation is approved, and the connection still has read access. Authorize again if you need to select a different key. ## An Action Is Denied [#an-action-is-denied] Read the tool's error and recovery instruction. Check the connection's execution access, session expiry, network installation, and permissions for that exact action. Change permissions in the dashboard only if you intend to grant more access. The agent cannot bypass a policy denial. ## A Request Stops After Submission [#a-request-stops-after-submission] If you have a submission ID, ask the agent to check that submission rather than repeat the transaction. A missing response does not prove the operation failed. ## Report a Problem [#report-a-problem] Include the client name, Namera version, operation, and error code or message. Remove credentials, private keys, encrypted exports, and sensitive account details from logs. The client owns the server process; inspect its MCP logs rather than redirecting protocol stdout into a log file. # Accounts and Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/accounts-and-session-keys Find an account and choose the session key your application will use. An **account** holds assets. A **session key** lets your application act on that account within its permissions. Create both in the [Namera dashboard](https://dashboard.namera.ai), or use the [account management SDK guides](https://namera.ai/docs/sdk/guides/accounts/create-accounts) with an explicitly permitted workspace API key. ## List Accounts [#list-accounts] Use a client configured with your [API key](https://namera.ai/docs/sdk/authentication): ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); const wallets = await namera.wallets.list(); if (!wallets.success) throw new Error(wallets.error.message); console.log(wallets.data); ``` Each account includes its `id`, `address`, and `metadata`. Use the account's `id` as `walletId` in SDK calls, not its address. ## Find Session Keys for an Account [#find-session-keys-for-an-account] Replace the example ID with an account ID from the list: ```ts title="index.ts" const walletId = "0199dfe1-0000-7000-8000-000000000001"; const sessions = await namera.sessionKeys.list({ walletId }); if (!sessions.success) throw new Error(sessions.error.message); console.log(sessions.data); ``` Omit `walletId` to list all session keys available to your credential. Each key includes its `walletId`, `policies`, and network `installations`. ## Use a Specific Session Key [#use-a-specific-session-key] Once you have chosen a key, keep its ID in your application's configuration. Retrieve it directly instead of relying on list order: ```ts title="index.ts" const sessionKeyId = "0199dfe1-0000-7000-8000-000000000002"; const result = await namera.sessionKeys.get(sessionKeyId); if (!result.success) throw new Error(result.error.message); const session = result.data; console.log(result.data); ``` Use `session.walletId` and `session.id` together when executing or signing. The key must be active, installed on the target network, and permitted to perform the operation. See [Permissions](https://namera.ai/docs/sdk/permissions). ## Get an Account by ID [#get-an-account-by-id] ```ts title="index.ts" const wallet = await namera.wallets.get(session.walletId); if (!wallet.success) throw new Error(wallet.error.message); console.log(wallet.data); ``` An empty list means no resources are available to this credential. Check the session-key grants and whether the key is still active in the dashboard. For a complete example using these resources, see [Getting Started](https://namera.ai/docs/sdk/getting-started). # Authentication > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/authentication Connect the SDK with an API key or OAuth access token. Use an **API key** for server-side scripts and services, or an **OAuth access token** for an authorized integration. Choose one authentication method per client. ## API Key [#api-key] Create an API key in the [Namera dashboard](https://dashboard.namera.ai) and select the session grants and explicit workspace management permissions your application needs. Copy the key when it is shown and save it in your environment: ```dotenv title=".env" NAMERA_API_KEY=your_api_key ``` Pass it to the client: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` For a local script, load `.env` when running it: ```sh node --env-file=.env index.ts ``` Keep API keys on your server and `.env` out of Git. Never include a key in browser code. An execution-only API key accesses accounts through its session grants. Explicit `wallet:read` and `session-key:read` permissions allow workspace-wide management reads. Creation, installation, removal, and revocation need their own [management permissions](https://namera.ai/docs/sdk/permissions#workspace-management-permissions). A key does not inherit its creator’s complete role. ## OAuth Access Token [#oauth-access-token] If your integration already has a Namera OAuth access token, pass it as `accessToken`: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ accessToken: process.env.NAMERA_ACCESS_TOKEN!, }); ``` Use the access token, not the refresh token. The client uses the scopes and session-key grants approved for that authorization. ### Refreshable Tokens [#refreshable-tokens] For a long-running integration, use `getAccessToken`. The SDK calls it before each request so your application can supply a current token. ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; export async function listAccounts(getAccessToken: () => Promise) { const namera = new NameraClient({ getAccessToken }); const wallets = await namera.wallets.list(); if (!wallets.success) throw new Error(wallets.error.message); return wallets.data; } ``` Pass your application's token-loading function to `listAccounts`. That function should refresh an expired token before returning it. The SDK does not run the OAuth flow or refresh tokens for you. ## Check Your Connection [#check-your-connection] With either client, inspect the authenticated identity and its grants: ```ts title="index.ts" const actor = await namera.auth.currentActor(); if (!actor.success) throw new Error(actor.error.message); console.log(actor.data); ``` If authentication fails, check that the credential has not expired or been revoked. If an account is missing, check its grants or workspace read permissions. To rotate an API key, create a replacement with the required grants, management permissions, and passkey origins, update your application, then revoke the old key in the dashboard. Next, [find your accounts and session keys](https://namera.ai/docs/sdk/accounts-and-session-keys). # Getting Started > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/getting-started Connect your workspace, send a test transaction, and check its status. Send a small test transaction on **Base Sepolia**. Add the TypeScript snippets to one `index.ts` file in order. ## Install the SDK [#install-the-sdk] ```sh npm install @namera-ai/sdk viem ``` ## Set Up Your Account [#set-up-your-account] In the [Namera dashboard](https://dashboard.namera.ai): 1. Create or choose an account. Choose a separate recipient wallet you control. 2. Create a **session key** that allows a native transfer to that recipient, with a spending limit of **0.001 ETH**. 3. Approve its installation on **Base Sepolia** and wait for it to become active. 4. Create an API key with access to only this session key for this walkthrough. Fund the account with **0.001 Base Sepolia test ETH** and save your API key: ```dotenv title=".env" NAMERA_API_KEY=your_api_key ``` Keep `.env` out of Git and API keys out of browser code. ## Create a Client [#create-a-client] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## List Accounts [#list-accounts] ```ts title="index.ts" const wallets = await namera.wallets.list(); if (!wallets.success) throw new Error(wallets.error.message); console.log(wallets.data); ```
```json [ { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" } ] ```
## List Session Keys [#list-session-keys] ```ts title="index.ts" const sessions = await namera.sessionKeys.list(); if (!sessions.success) throw new Error(sessions.error.message); console.log(sessions.data); const session = sessions.data[0]; if (!session) throw new Error("Grant this API key access to your session key."); ``` This uses the first key returned. For this walkthrough, your API key should only have access to the session key you just configured.
```json [ { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000006", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send 0.001 test ETH on Base Sepolia" }, "policies": [], "policyHash": "1111111111111111111111111111111111111111111111111111111111111111", "status": "active", "revokedAt": null, "createdAt": "2026-10-11T09:05:00.000Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000000007", "userId": "0199dfe1-0000-7000-8000-000000000008", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationRoleId": "0199dfe1-0000-7000-8000-000000000009", "joinedAt": "2026-10-11T08:00:00.000Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000000008", "email": "developer@example.com", "emailVerified": true, "metadata": { "version": 1, "name": "Example developer", "image": { "type": "emoji", "value": "πŸ‘€" } }, "lastLoginAt": "2026-10-11T08:55:00.000Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000000009", "key": "developer", "metadata": { "version": 1, "name": "Developer", "logo": { "type": "emoji", "value": "πŸ’»" }, "description": "Manage test accounts and session keys" }, "type": "custom", "permissions": [ "wallet:read", "wallet:create", "session-key:read", "session-key:create", "api-key:create" ], "systemRoleId": null } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000010", "chainId": "eip155:84532", "status": "installed", "authorization": { "version": 1, "entityId": 1, "signerAddress": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf", "permissions": [ { "type": "contract-access", "address": "0x2222222222222222222222222222222222222222" }, { "type": "native-token-transfer", "allowance": "1000000000000000" } ], "allowSignatures": false, "validAfter": 1791709200, "validUntil": 1794387600 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ] ```
## Execute a Transaction [#execute-a-transaction] This sends **0.001 test ETH** on Base Sepolia. Replace the example address below with the separate recipient wallet allowed by your session key. ```ts title="index.ts" import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: session.walletId, sessionKeyId: session.id, chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` The selected key must permit the call and be installed on Base Sepolia. Gas sponsorship uses your workspace's allowance; it does not fund the transfer. `prepared` means the operation is queued for broadcast.
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
## Get Submission Status [#get-submission-status] Use the submission ID from the execution result: ```ts title="index.ts" const status = await namera.executions.getStatus(execution.data.submissionId); if (!status.success) throw new Error(status.error.message); console.log(status.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
Check the same submission again after a short delay while its status is `reserved`, `prepared`, or `submitted`. Stop on `confirmed` or `failed`. - **Confirmed:** `status.data.execution` contains the execution record. - **Failed:** the submission did not complete successfully. `success: true` means the SDK request succeeded. Read `data.status` for the transaction outcome. Poll the existing submission instead of calling `execute()` again to check progress. ## Run It [#run-it] Run from the directory containing `index.ts` and `.env`: ```sh node --env-file=.env index.ts ``` The script submits **one new transaction each time you run it** and checks its status once. To check that same transaction later, keep its submission ID and call only `getStatus()`. For message signing, see the [quick examples](https://namera.ai/docs/sdk#quick-examples). # Create Accounts > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/accounts/create-accounts Provision managed or passkey-owned accounts from your backend. Create an API key in **Settings β†’ Workspace β†’ API keys** with `wallet:create` and `wallet:read`. These permissions cover all existing and future accounts in that workspace. Keep the API key in your backend environment. ## Create a managed account [#create-a-managed-account] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Provisioned account" }, owner: { type: "namera-managed", provider: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "metadata": { "version": 1, "name": "Provisioned account" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000008", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:39:05.250Z", "updatedAt": "2026-10-15T02:39:05.250Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x52e7f17258368d7f9Ebd7bDf8d6869Bc4759aBA1", "salt": "0" } } ```
The account is derived and persisted without deploying it. The SDK manages managed-provisioning retry keys internally. Keep the returned ID; use it as `walletId` when creating sessions. ## Create a passkey-owned account [#create-a-passkey-owned-account] At API-key issuance, allowlist your application’s exact origin, such as `https://app.example.com`. Each passkey belongs to that RP and origin. Your backend must authenticate its application user and bind the pending verification ID to that user. ### Start on your backend [#start-on-your-backend] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.wallets.createPasskeyRegistrationOptions({ origin: "https://app.example.com", user: { name: "Customer", displayName: "Customer" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "verificationId": "0199dfe1-0000-7000-8000-000000000022", "options": { "challenge": "OuAZdeWe1cPGP8if-E91tdEwtCgFVy68KEuEyXdtaIY", "rp": { "id": "app.example.com", "name": "Namera" }, "user": { "id": "MDFhMTNkNmQtNzZkYi03NTUzLWE4M2QtMTFhMzRkNWJhNjFm", "name": "Customer", "displayName": "Customer" }, "pubKeyCredParams": [ { "alg": -7, "type": "public-key" } ], "timeout": 300000, "excludeCredentials": [], "authenticatorSelection": { "residentKey": "required", "requireResidentKey": true, "userVerification": "required" }, "hints": [], "attestation": "none", "extensions": { "credProps": true } }, "expiresAt": "2026-10-15T02:44:06.347Z" } ```
Persist `verificationId` in your user’s pending account creation and return `options` to their browser. Do not expose the API key. Your application owns the start/finish HTTP routes; these are not additional Namera endpoints. ### Register in the browser [#register-in-the-browser] Install `@simplewebauthn/browser` in your frontend. In a user-initiated event, call `startRegistration({ optionsJSON: options })` with the options your backend returned. Send the complete result to your backend. Browser cancellation should leave the account uncreated. ### Finish on your backend [#finish-on-your-backend] Load `verificationId` from that authenticated user’s pending creation and submit: ```ts title="index.ts" import { NameraClient, type CreateWalletRequest } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); export async function finishPasskeyAccount( verificationId: string, response: Extract["response"], ) { const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Customer account" }, owner: { type: "passkey", verificationId, response }, }); if (!result.success) throw new Error(result.error.message); return result.data; } ```
```json { "id": "0199dfe1-0000-7000-8000-000000000004", "organizationId": "0199dfe1-0000-7000-8000-000000000015", "metadata": { "version": 1, "name": "Customer account" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000016", "custody": "local", "algorithm": "p256" }, "createdAt": "2026-10-15T02:39:06.474Z", "updatedAt": "2026-10-15T02:39:06.474Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "webauthn_p256", "entryPointVersion": "0.7", "salt": "0", "entityId": 0 } } ```
The exported function is called by your authenticated finish route after it loads the pending verification. It is not an unauthenticated route accepting arbitrary verification IDs. Registration is single-use and actor-bound. Passkey creation is not automatically retried after a lost response; inspect the workspace account list before attempting a new ceremony. Next, [create a session key](https://namera.ai/docs/sdk/guides/accounts/create-session-keys). # Create Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/accounts/create-session-keys Register a managed or caller-held session signer. Issue an API key with `session-key:create`, `session-key:read`, and `wallet:read`. You need an account ID in that workspace. Session custody is independent of account ownership: both signer types work with either account owner. ## Create a managed session [#create-a-managed-session] The following example deliberately requests root authority for one hour on Sepolia, with message signatures disabled. Root sessions can control the account; select narrower onchain permissions for restricted agents. ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "id": "0199dfe1-0000-7000-8000-000000000003", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000012", "namespace": "eip155", "metadata": { "version": 1, "name": "Local agent" }, "policies": [], "policyHash": "9Z4ZzPfiQ4hIUpSXTY_nQ2E9-kjd2w_5wbLwIj7visI", "status": "pending", "revokedAt": null, "createdAt": "2026-10-15T02:39:05.307Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x04e37a5065266fa599595e06a6968cdfe2d588cfbbbbb48f0d4c504048c53786a87ff061f472d579833ea98e99f425febabd2445a8760e225cb1e5b4a029cd18b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "metadata": { "version": 1, "name": "Provisioned account" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000008", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:39:05.250Z", "updatedAt": "2026-10-15T02:39:05.250Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x52e7f17258368d7f9Ebd7bDf8d6869Bc4759aBA1", "salt": "0" } }, "creator": { "type": "api-key", "actorId": "0199dfe1-0000-7000-8000-000000000009", "id": "0199dfe1-0000-7000-8000-000000000010", "metadata": { "version": 1, "name": "Workspace backend" } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000013", "chainId": "eip155:11155111", "status": "pending", "authorization": { "version": 1, "entityId": 142534698, "signerAddress": "0x7838CE7D0AC8943A2fAA4e8ab8ae901b05eA7A03", "permissions": [ { "type": "root" } ], "allowSignatures": false, "validAfter": 1792031945, "validUntil": 1792035545 }, "installTransactionHash": null, "uninstallTransactionHash": null } ] } ```
The SDK manages managed-provisioning idempotency internally. Namera returns public signer information only. ## Create a local session [#create-a-local-session] Install `viem` alongside `@namera-ai/sdk`. Generate and securely persist your private key locally before registering its public key: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const privateKey = generatePrivateKey(); const signer = privateKeyToAccount(privateKey); // Persist the private key in your secure signer store before registration. const now = Math.floor(Date.now() / 1000); const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "local", algorithm: "secp256k1", publicKey: signer.publicKey }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: now, validUntil: now + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000007", "namespace": "eip155", "metadata": { "version": 1, "name": "Local agent" }, "policies": [], "policyHash": "9Z4ZzPfiQ4hIUpSXTY_nQ2E9-kjd2w_5wbLwIj7visI", "status": "pending", "revokedAt": null, "createdAt": "2026-10-15T02:39:05.274Z", "signer": { "custody": "local", "algorithm": "secp256k1", "publicKey": "0x04118cf91563c3c7b00440980e879331bdac649585ea668f5dfdb0d925ae6bc4bc2ce5449ea5eabee69642fa1b6df0dce03b2dc3e7ae4498878013772fdd155cb6" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "metadata": { "version": 1, "name": "Provisioned account" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000008", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:39:05.250Z", "updatedAt": "2026-10-15T02:39:05.250Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x52e7f17258368d7f9Ebd7bDf8d6869Bc4759aBA1", "salt": "0" } }, "creator": { "type": "api-key", "actorId": "0199dfe1-0000-7000-8000-000000000009", "id": "0199dfe1-0000-7000-8000-000000000010", "metadata": { "version": 1, "name": "Workspace backend" } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000011", "chainId": "eip155:11155111", "status": "pending", "authorization": { "version": 1, "entityId": 145278918, "signerAddress": "0xdA46572b24FF407Cb8979412281cEA774087E5d7", "permissions": [ { "type": "root" } ], "allowSignatures": false, "validAfter": 1792031945, "validUntil": 1792035545 }, "installTransactionHash": null, "uninstallTransactionHash": null } ] } ```
The private key never enters a Namera request. Public-key registration does not populate the SDK’s Node signer store. For execution, configure your trusted local signer binding or use the existing encrypted local-key import flow. Retain the signer after a lost registration response; do not generate a replacement key as a retry. ## Approve installation separately [#approve-installation-separately] Creation grants the calling API-key actor access to the new session, but does not install it. Each installation starts pending. [Install the session](https://namera.ai/docs/sdk/guides/accounts/install-session-keys) before executing or signing. # Install Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/accounts/install-session-keys Explicitly approve and track session installation from the SDK. Use an API key with `session-key:read` and `session-key:install`. You need a registered session with an unexpired pending installation on the chosen network. The account’s owner determines approval; the session signer’s custody does not. These are low-level owner-operation methods. Review the selected account, signer, permissions, network, validity, and fees before approving. Use the SDK’s `validateManagedOwnerApproval` or `validateOwnerApproval` helpers with independently reconstructed expectations when validating prepared calldata. Do not populate those expectations from the preparation you are validating. ## Prepare installation [#prepare-installation] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); 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); ```
```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" } ```
The SDK resolves the session’s network installation and account owner, then chooses the existing managed or passkey preparation endpoint. Retry keys stay internal. Preparation does not sign or submit. ## Approve a managed account operation [#approve-a-managed-account-operation] After reviewing and validating the preparation, explicitly approve its operation ID: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.sessionKeys.approveOperation({ operationId: "0199dfe1-0000-7000-8000-000000000014", approval: { type: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "operationId": "0199dfe1-0000-7000-8000-000000000014", "status": "signed" } ```
This call authorizes the managed account owner to sign only the stored installation. Creating the session did not grant this approval. ## Approve a passkey account operation [#approve-a-passkey-account-operation] Passkey preparation returns `approval: "passkey"` and `options`:
```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" } ```
Return the preparation to your application’s browser for review and validation. Install `@simplewebauthn/browser` in your frontend and call `startAuthentication({ optionsJSON: preparation.options })` from a user action. The prompt must run on the account’s stored origin. Keep the API key on your backend. Send the assertion to your authenticated backend, which loads the pending operation ID belonging to that user and calls: ```ts title="index.ts" import { NameraClient, type ApproveSessionKeyOperationRequest } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); export async function finishPasskeyInstallation( operationId: string, response: Extract["response"], ) { const result = await namera.sessionKeys.approveOperation({ operationId, approval: { type: "passkey", response }, }); if (!result.success) throw new Error(result.error.message); return result.data; } ``` The success shape is the same operation status shown above. Namera verifies the actual assertion; an API-key permission does not replace the passkey signature. ## Track confirmation and recover interruptions [#track-confirmation-and-recover-interruptions] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.sessionKeys.getOperation("0199dfe1-0000-7000-8000-000000000014"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "operationId": "0199dfe1-0000-7000-8000-000000000014", "status": "confirmed" } ```
Workers submit signed requests and reconcile receipts. `signed` and `submitted` are not confirmation. Check the session installation for `installed` before using it. After a restart, call `sessionKeys.getActiveOperation({ sessionKeyId, chainId, kind: "install" })`. An unsigned operation includes a recovered `preparation`; review it before explicit approval. Signed/submitted operations include no preparation and should be polled. No caller-managed idempotency key is needed. `cancelOperation(operationId)` cancels an unsigned preparation; it cannot cancel signed work. # Revoke and Remove Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/accounts/revoke-session-keys Stop Namera access and remove remaining onchain authority. Use `session-key:revoke`, `session-key:uninstall`, and `session-key:read` on a workspace management key. These are separate permissions and actions. ## Revoke Namera access [#revoke-namera-access] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.sessionKeys.revoke("0199dfe1-0000-7000-8000-000000001000"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "id": "0199dfe1-0000-7000-8000-000000001000", "organizationId": "0199dfe1-0000-7000-8000-000000001001", "walletId": "0199dfe1-0000-7000-8000-000000001002", "signingKeyId": "0199dfe1-0000-7000-8000-000000001003", "namespace": "eip155", "metadata": { "version": 1, "name": "Local agent" }, "policies": [], "policyHash": "9Z4ZzPfiQ4hIUpSXTY_nQ2E9-kjd2w_5wbLwIj7visI", "status": "revoking", "revokedAt": "2026-10-15T02:57:34.211Z", "createdAt": "2026-10-15T02:57:32.375Z", "signer": { "custody": "local", "algorithm": "secp256k1", "publicKey": "0x04c70cd5e6b1350f36bb3f47e4c50f276178a843ddc457189b962b660b81945ccee5bd6e75bbf22348c1ece286baeec6776e5cc66206f2b5de96cf0c8a0ca407e1" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000001002", "organizationId": "0199dfe1-0000-7000-8000-000000001001", "metadata": { "version": 1, "name": "Managed owner" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000001004", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:57:32.345Z", "updatedAt": "2026-10-15T02:57:32.345Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x90C59223ac50061f5204826078944ec41bc56e0d", "salt": "0" } }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000001005", "userId": "0199dfe1-0000-7000-8000-000000001006", "organizationId": "0199dfe1-0000-7000-8000-000000001001", "organizationRoleId": "0199dfe1-0000-7000-8000-000000001007", "joinedAt": "2026-10-15T02:57:32.244Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000001006", "email": "0199dfe1-0000-7000-8000-000000001008@example.com", "emailVerified": true, "metadata": { "version": 1 }, "lastLoginAt": "2026-10-15T02:57:32.211Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000001007", "key": "owner", "permissions": [ "organization:read", "organization:update", "member:read", "member:update", "member:remove", "invitation:read", "invitation:create", "invitation:cancel", "role:read", "role:create", "role:update", "role:delete", "billing:read", "billing:update", "billing:cancel", "wallet:read", "wallet:create", "wallet:update", "session-key:read", "session-key:create", "session-key:revoke", "api-key:read", "api-key:create", "api-key:revoke", "execution:read", "mcp-authorization:read", "mcp-authorization:create", "mcp-authorization:revoke", "cli-authorization:read", "cli-authorization:create", "cli-authorization:revoke" ], "metadata": { "version": 1, "name": "Owner", "description": "Organization owner with full access" }, "type": "system", "systemRoleId": "0199dfe1-0000-7000-8000-000000001009" } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000001010", "chainId": "eip155:11155111", "status": "installed", "authorization": { "version": 1, "entityId": 94541820, "signerAddress": "0xAB592704Fde287292b3a886Db80C0B6e7AC6DAdc", "permissions": [ { "type": "root" } ], "allowSignatures": false, "validAfter": 1792033052, "validUntil": 1792036652 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ```
The complete returned session retains its installation state. Its grants are revoked immediately and unsigned installation requests are cancelled. Installed or signed authority can keep the session `revoking`; a never-installed session can finish immediately. ## Remove installed networks [#remove-installed-networks] For each remaining installed network: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const result = await namera.sessionKeys.prepareOperation({ sessionKeyId: "0199dfe1-0000-7000-8000-000000001000", chainId: "eip155:11155111", kind: "uninstall", sponsor: true, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ```
```json { "operationId": "0199dfe1-0000-7000-8000-000000001011", "namespace": "eip155", "approval": "1claw", "prepared": { "version": 1, "namespace": "eip155", "chainId": "eip155:11155111", "entryPointVersion": "0.7", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "sponsorship": "none", "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": "0xabcd" } ], "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-15T03:02:34.211Z" } ```
Preparation contains the stored removal calldata. Follow the [explicit approval flow](https://namera.ai/docs/sdk/guides/accounts/install-session-keys) and poll `getOperation()` until confirmed. A local signer can act outside Namera until its onchain authority is removed. You may remove one network from an active session without revoking its other network installations. To retire the entire session, revoke server access and remove every installed network. Missing receipts are not proof of removal or failure; let reconciliation resolve signed work. # Sign Messages > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/signing/sign-messages Sign a text message with your account and an authorized session key. Use `namera.sign()` with `type: "message"` to sign a UTF-8 string. Signing a message does not submit a transaction. ## Before You Start [#before-you-start] Set up [authentication](https://namera.ai/docs/sdk/authentication) and a session key installed on **Base Sepolia**. The installation needs signature authority, and its API signature policy must allow `message` signing. See [Permissions](https://namera.ai/docs/sdk/permissions#message-and-typed-data-signing). ```sh npm install @namera-ai/sdk ``` ## Sign a Message [#sign-a-message] Replace the IDs with your account and session key: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "signature": "0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b", "type": "message" } ```
The response values are illustrative. Use the actual `signature` returned by your request, with the original message, account, and network. ## Verify the Signature [#verify-the-signature] ```ts title="index.ts" const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "message", message, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "valid": true, "type": "message" } ```
Check `verification.data.valid`, not just `success`. These are smart-account signatures; use [Verify Signatures](https://namera.ai/docs/sdk/guides/signing/verify-signatures) rather than comparing a recovered EOA address. For structured payloads, use [Sign Typed Data](https://namera.ai/docs/sdk/guides/signing/sign-typed-data). # Sign Typed Data > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/signing/sign-typed-data Sign structured EIP-712 data with your account. Use `namera.sign()` with `type: "typed-data"` for EIP-712 payloads. The domain, types, primary type, and message together define what is signed. ## Before You Start [#before-you-start] Use an [authenticated client](https://namera.ai/docs/sdk/authentication) and a session key installed on **Base Sepolia** with signature authority. Its API signature policy must allow `typed-data` and match any configured domain rules. ```sh npm install @namera-ai/sdk ``` ## Define the Payload [#define-the-payload] This example signs a `Greeting` for your application. Replace the verifying contract with your application's contract on Base Sepolia, and use the domain and types expected by that application. ```ts title="index.ts" import { NameraClient, type EvmTypedData } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const typedData = { domain: { name: "Namera Example", version: "1", chainId: 84532, verifyingContract: "0x3333333333333333333333333333333333333333", }, types: { Greeting: [{ name: "contents", type: "string" }], }, primaryType: "Greeting", message: { contents: "Hello from Namera" }, } satisfies EvmTypedData; ``` The domain uses the numeric chain ID `84532`. The SDK request uses the network identifier `eip155:84532`. ## Sign the Payload [#sign-the-payload] Replace the account and session-key IDs with your own: ```ts title="index.ts" const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "typed-data", typedData, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "signature": "0x0000000100222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222221b", "type": "typed-data" } ```
The signature above is illustrative. Keep the actual signature and the exact payload you signed for [verification](https://namera.ai/docs/sdk/guides/signing/verify-signatures). ## Use Integer Values [#use-integer-values] Typed-data messages must be JSON-compatible. For large integer fields such as `uint256`, use decimal strings rather than JavaScript `bigint` values or numbers that lose precision. This differs from transaction `value`, which accepts a `bigint`. ## Match Your Signature Policy [#match-your-signature-policy] When your session has typed-data rules, one rule must match the chain, verifying contract, primary type, and any configured domain name and version. Domain names and versions are case-sensitive. These rules restrict the payload's domain and type, not the amounts inside a permit or other authorization. Review the actual message before signing. Signing returns a signature; it does not submit the payload to the target contract. # Verify Signatures > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/signing/verify-signatures Check a smart-account signature against its original message or typed data. Use `verifySignature()` with the original payload, account ID, network, and signature. Verification is read-only and does not need a `sessionKeyId`. Your credential must still have access to the account. ## Verify a Message [#verify-a-message] This runnable example signs a message, then verifies the returned signature. Use [authentication](https://namera.ai/docs/sdk/authentication) and replace the IDs with an account and session key configured for [message signing](https://namera.ai/docs/sdk/guides/signing/sign-messages). ```sh npm install @namera-ai/sdk ``` ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const walletId = "0199dfe1-0000-7000-8000-000000000001"; const sessionKeyId = "0199dfe1-0000-7000-8000-000000000002"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId, sessionKeyId, chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); const verification = await namera.verifySignature({ namespace: "eip155", walletId, chainId: "eip155:84532", type: "message", message, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "valid": true, "type": "message" } ```
If you already have a signature, skip `sign()` and pass that signature to `verifySignature()`. Preserve the original message exactly, including whitespace. ## Verify Typed Data [#verify-typed-data] After [signing typed data](https://namera.ai/docs/sdk/guides/signing/sign-typed-data), add this snippet to that example. It uses the existing `namera`, `typedData`, and successful `signed` result from that page: ```ts title="index.ts" const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "typed-data", typedData, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "valid": true, "type": "typed-data" } ```
Supply the same domain, types, primary type, and message that were signed. Changing a field changes the payload being verified. ## Read the Outcome [#read-the-outcome] `success: true` means the verification request completed. Only `data.valid: true` means the signature was accepted for that account and payload. Treat `valid: false` as an invalid signature; handle `success: false` as a request error. Namera returns smart-account signatures. Recovering an EOA address from the signature is not a substitute for checking the account's signature validation. # Batch Transactions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/batch-transactions Submit multiple calls in one execution. Put multiple calls in the `calls` array to submit them together. A batch uses one account, one session key, and one network, with a single submission ID to track. ## Before You Start [#before-you-start] Set up [authentication](https://namera.ai/docs/sdk/authentication). Your session key must be installed on **Base Sepolia**, allow both recipients, and permit the combined **0.002 ETH** transfer. Fund the account with **0.002 test ETH**. ```sh npm install @namera-ai/sdk viem ``` ## Submit a Batch [#submit-a-batch] Replace the IDs and both recipients with your own. Calls are executed in array order. ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; import { parseEther } from "viem"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const batch = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, { to: "0x4444444444444444444444444444444444444444", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!batch.success) throw new Error(batch.error.message); console.log(batch.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
Every call must pass the selected session key's permissions and policies. Native spending limits apply to the sum of all call values, not each transfer individually. A batch cannot combine authority from different session keys. ## Combine Different Calls [#combine-different-calls] The array can contain native transfers and [encoded contract calls](https://namera.ai/docs/sdk/guides/transactions/interact-with-contracts). For dependent calls, such as approval followed by a contract interaction, put the prerequisite first and ensure both calls are permitted. [Simulate the full batch](https://namera.ai/docs/sdk/guides/transactions/simulate-transactions) before submitting it, then [track its submission](https://namera.ai/docs/sdk/guides/transactions/track-transactions). # Handle Retries and Recovery > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/handle-retries-and-recovery Recover from interrupted requests without submitting duplicate transactions. When a request fails, first determine whether you have a `submissionId`. If you do, check that submission. A new `executions.execute()` call creates a new operation, even when its parameters are identical. ## Understand Automatic Retries [#understand-automatic-retries] During `execute()`, the SDK retries transient preparation and completion failures up to three times each, with exponential backoff starting at 100 ms. Preparation retries reuse the same idempotency key. Completion retries reuse the same submission and, when supplied, the same signature. Eligible failures are transport errors, HTTP 408, HTTP 5xx, and the declared `InternalServerError`. Policy denials, authentication failures, rate limits, and other declared business errors are not automatically retried. These retries happen **inside one call**. There is no public idempotency-key option on `execute()` to deduplicate separate calls or process restarts. A lost response does not prove that the transaction failed. Wrapping `execute()` in a retry loop can send the same transfer twice. ## Save the Submission ID [#save-the-submission-id] After a successful `execute()` result, save `result.data.submissionId` with your application's job or payment record before marking that work as submitted. Keep the intended account, network, recipient, and amount with the same record. Persist this in durable storage, not just a process variable or console log. See [Execute a Transaction](https://namera.ai/docs/sdk/reference/executions/execute) for the request and full submission response. Prevent concurrent workers from executing the same application job. An application-level job ID helps coordinate your workers; it is not a Namera idempotency key and does not close the gap between submission and saving its ID. ## Resume Status Checks [#resume-status-checks] Install `@namera-ai/sdk`, set `NAMERA_API_KEY`, and replace the example ID with the submission saved for your job. This Node.js example checks for up to one minute. It retries failed **reads**, never the transaction: ```ts title="index.ts" import { setTimeout } from "node:timers/promises"; import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const submissionId = "0199dfe1-0000-7000-8000-000000000003"; const deadline = Date.now() + 60_000; let settled = false; while (Date.now() < deadline) { const result = await namera.executions.getStatus(submissionId); let delay = 3000; if (!result.success) { const { error } = result; if (error.kind === "api" && error.cause._tag === "RateLimitExceeded") { delay = Math.max(delay, error.cause.retryAfterSeconds * 1000); } else if ( error.kind !== "network" && !(error.kind === "api" && error.cause._tag === "InternalServerError") && !(error.status === 408 || (error.status !== null && error.status >= 500)) ) { throw new Error(error.message); } } else { console.log(result.data); if (result.data.status === "confirmed" || result.data.status === "failed") { settled = true; break; } } if (Date.now() + delay >= deadline) break; await setTimeout(delay); } if (!settled) { console.log("Status is unresolved. Keep the submission ID and check again later."); } ``` A pending response has this shape:
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
The time limit stops new checks; it does not cancel an in-flight request or the transaction. If a rate-limit delay exceeds the remaining time, wait that delay before resuming in a later run. - **`reserved`, `prepared`, or `submitted`**: keep tracking the same ID. - **`confirmed`**: store the returned execution and mark the job complete. - **`failed`**: stop polling and investigate before intentionally starting a replacement operation. See [Get Submission Status](https://namera.ai/docs/sdk/reference/executions/get-submission-status) for all response variants. `getStatus()` itself does not retry automatically; the example above supplies a bounded policy for read failures. ## Recover Without a Submission ID [#recover-without-a-submission-id] If `execute()` fails before returning an ID, or your process stops before saving it, mark the application job as **unresolved**, not ready to retry. The error result does not expose the internally prepared submission ID. Inspect [execution history](https://namera.ai/docs/sdk/reference/executions/list-executions) and [execution details](https://namera.ai/docs/sdk/reference/executions/get-execution) for a matching confirmed operation. Compare the account, network, calls, and timing. Identical transfers can be legitimate, so matching values alone do not uniquely identify your job. History contains confirmed executions only. An empty history result does not rule out a pending submission. If you cannot establish the outcome, keep the job unresolved and reconcile it before allowing another execution. ## Fix Errors Before Resubmitting [#fix-errors-before-resubmitting] Correct invalid inputs, credentials, permissions, or funding before starting a replacement operation. For a paused network, wait for it to be enabled again. Do not treat a transport failure as evidence that these checks rejected the original transaction. For rate limits, respect `retryAfterSeconds`; see [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors). The same caution applies to signing: a lost `sign()` response is not a reason to repeat it automatically, since another call can create another billable signing operation. # Interact with Contracts > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/interact-with-contracts Encode and execute a smart-contract function call. Pass a contract address and encoded function call to `executions.execute()`. The contract receives the call from your Namera account. ## Before You Start [#before-you-start] Use an [authenticated client](https://namera.ai/docs/sdk/authentication) and a session key installed on **Base Sepolia**. Its permissions must allow the target contract and function. ```sh npm install @namera-ai/sdk viem ``` ## Call a Function [#call-a-function] This example calls `setGreeting(string)` on a contract you have deployed. Replace the IDs and contract address with your own, and use the ABI of the contract you are calling. ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; import { encodeFunctionData, parseAbi } from "viem"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const abi = parseAbi(["function setGreeting(string greeting)"]); const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x3333333333333333333333333333333333333333", value: 0n, data: encodeFunctionData({ abi, functionName: "setGreeting", args: ["Hello from Namera"], }), }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
The response identifies the submission, not the function's return value. [Track it](https://namera.ai/docs/sdk/guides/transactions/track-transactions) to confirm execution. ## Send ETH with a Call [#send-eth-with-a-call] For a **payable** function, set the call's `value` with `parseEther`: ```ts title="index.ts" import { parseEther } from "viem"; const value = parseEther("0.001"); ``` Use this value in place of `0n` only when the target function accepts ETH. The `setGreeting` example above is not payable. The account needs enough ETH and the session key must allow the native transfer as well as the function call. Before submitting a new contract interaction, [simulate the transaction](https://namera.ai/docs/sdk/guides/transactions/simulate-transactions). # Simulate Transactions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/simulate-transactions Preview calls and check installed permissions before submitting. Use `executions.simulate()` to inspect a transaction without signing or submitting it. Simulation does not reserve billing allowance. ## Simulate a Transfer [#simulate-a-transfer] Use an [authenticated client](https://namera.ai/docs/sdk/authentication) and a session key installed on **Base Sepolia**. The account needs the test ETH being transferred. Replace the example IDs and recipient with your own. ```sh npm install @namera-ai/sdk viem ``` ```ts title="index.ts" import { NameraClient, type SimulateExecutionRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const request = { namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies SimulateExecutionRequest; const simulation = await namera.executions.simulate(request); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ```
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "callsSucceeded": true, "simulation": { "userOperation": { "source": "eth_estimateUserOperationGas", "callGasLimit": "50000", "verificationGasLimit": "100000", "preVerificationGas": "50000", "maxFeePerGas": "1000000000", "maxPriorityFeePerGas": "1000000" }, "calls": { "source": "viem.simulateCalls", "results": [{ "status": "success", "returnData": "0x", "gasUsed": "21000" }], "assetChanges": [], "transfers": [ { "callIndex": 0, "from": "0x1111111111111111111111111111111111111111", "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000" } ] } }, "allowed": true, "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002" } ```
Gas estimates are illustrative. Quantities shown as decimal strings in JSON are `bigint` values in the SDK. ## Read the Result [#read-the-result] - `callsSucceeded` reports whether the simulated calls succeeded. - `allowed` reports point-in-time eligibility for the selected session key. - `simulation.calls` contains per-call results, detected asset changes, and native transfers. If simulation itself fails, the SDK returns `success: false`; handle it as an [error](https://namera.ai/docs/sdk/handling-results-and-errors). ## Execute the Same Calls [#execute-the-same-calls] After reviewing the result, submit the same request with sponsorship enabled: ```ts title="index.ts" if (!simulation.data.callsSucceeded || !simulation.data.allowed) { throw new Error("Review the simulation before executing."); } const execution = await namera.executions.execute({ ...request, sponsor: true }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
Balances, permissions, and available budgets can change after simulation. Execution checks them again. The second snippet submits a real testnet transaction. Next, [track the submission](https://namera.ai/docs/sdk/guides/transactions/track-transactions). # Sponsor Gas > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/sponsor-gas Choose sponsored execution or pay gas from your account. Namera sponsors gas by default. Set `sponsor: false` to pay gas from your account instead. The same execution method supports both options. ## Set Up the Transfer [#set-up-the-transfer] Set up [authentication](https://namera.ai/docs/sdk/authentication) and a session key installed on **Base Sepolia** with permission to send **0.001 test ETH**. Replace the IDs and recipient below with your own. ```sh npm install @namera-ai/sdk viem ``` ```ts title="index.ts" import { NameraClient, type ExecuteRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const transfer = { namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies ExecuteRequest; ``` Choose one of the following options. Each example submits a new transfer. ## Use Sponsored Gas [#use-sponsored-gas] ```ts title="index.ts" const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const sponsored = await namera.executions.execute({ ...transfer, sponsor: true }); if (!sponsored.success) throw new Error(sponsored.error.message); console.log(sponsored.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
Omitting `sponsor` has the same effect as `sponsor: true`. Sponsorship is subject to your workspace's plan and available allowance. The account still needs the assets being transferred. Installed session-key permissions, including gas limits, still apply. ## Pay Gas from Your Account [#pay-gas-from-your-account] Set `maxGasCostWei` on the client and pass `sponsor: false` to the execution. Here, **0.0001 ETH** is the maximum gas cost you approve for the operation: ```ts title="index.ts" const selfFundedClient = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, maxGasCostWei: parseEther("0.0001"), }); const selfFunded = await selfFundedClient.executions.execute({ ...transfer, sponsor: false, }); if (!selfFunded.success) throw new Error(selfFunded.error.message); console.log(selfFunded.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000011", "status": "prepared", "userOperationHash": "0x2222222222222222222222222222222222222222222222222222222222222222" } ```
Fund the account with enough ETH on the selected network for the transfer and gas. The ceiling is not a gas price or an extra payment. The SDK rejects a prepared operation that exceeds it; choose a ceiling you are willing to pay. Self-funded execution does not use sponsored-gas credits, but still counts toward execution usage. With either option, [track the submission](https://namera.ai/docs/sdk/guides/transactions/track-transactions) to read the final outcome. # Track Transactions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/track-transactions Follow a submission to confirmation and read its execution record. Save the `submissionId` returned by `executions.execute()`. Use it to check progress without submitting the transaction again. ## Check a Submission [#check-a-submission] Use your [API key](https://namera.ai/docs/sdk/authentication) and replace the example submission ID with the one returned by your execution: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const submissionId = "0199dfe1-0000-7000-8000-000000000003"; const status = await namera.executions.getStatus(submissionId); if (!status.success) throw new Error(status.error.message); console.log(status.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
## Follow the Status [#follow-the-status] - **`reserved`**: waiting for a signature. - **`prepared`**: signed and queued for broadcast. - **`submitted`**: observed by the bundler; not yet confirmed. - **`confirmed`**: completed successfully, with an execution record. - **`failed`**: did not complete successfully. Poll the same submission until it reaches a terminal status. This example checks every three seconds for up to one minute: ```ts title="index.ts" for (let attempt = 0; attempt < 20; attempt++) { const latest = await namera.executions.getStatus(submissionId); if (!latest.success) throw new Error(latest.error.message); console.log(latest.data); if (latest.data.status === "confirmed" || latest.data.status === "failed") break; await new Promise((resolve) => setTimeout(resolve, 3000)); } ``` If it is still pending, keep the ID and check again later. Reaching the polling limit does not mean the transaction failed. Each new `execute()` call starts a new operation. Poll `getStatus()` instead. A failed or missing response alone does not prove that no transaction was submitted. ## Read a Confirmed Execution [#read-a-confirmed-execution] Once confirmed, `data.execution` contains the calls, transaction hash, and receipt. For the 0.001 ETH transfer, a confirmed response has this shape:
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "confirmed", "execution": { "id": "0199dfe1-0000-7000-8000-000000000012", "executionSubmissionId": "0199dfe1-0000-7000-8000-000000000003", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "sessionKeyGrantId": "0199dfe1-0000-7000-8000-000000000013", "namespace": "eip155", "data": { "version": 1, "chainId": "eip155:84532", "calls": [ { "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000", "data": "0x" } ], "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "receipt": { "version": 1, "namespace": "eip155", "chainId": "eip155:84532", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "blockHash": "0x6666666666666666666666666666666666666666666666666666666666666666", "blockNumber": "32000000", "sender": "0x1111111111111111111111111111111111111111", "nonce": "0", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "paymaster": null, "actualGasCost": "0", "actualGasUsed": "120000", "success": true, "reason": null } }, "createdAt": "2026-10-11T09:10:00.000Z" } } ```
Hashes and receipt values are illustrative. Quantities shown as decimal strings in JSON are `bigint` values in the SDK. Use `execution.data.transactionHash` to look up the transaction on the network's block explorer. The `userOperationHash` identifies the account operation and is not the transaction hash. ## Read Execution History [#read-execution-history] Filter confirmed executions by account or session key: ```ts title="index.ts" const history = await namera.executions.list({ walletId: "0199dfe1-0000-7000-8000-000000000001", }); if (!history.success) throw new Error(history.error.message); console.log(history.data); ```
```json { "items": [ { "details": { "id": "0199dfe1-0000-7000-8000-000000000012", "namespace": "eip155", "chainId": "eip155:84532", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "createdAt": "2026-10-11T09:10:00.000Z" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" } }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send test ETH on Base Sepolia" } }, "actorType": "api-key" } ], "nextCursor": null } ```
When `nextCursor` is not `null`, pass it as `cursor` with the same filters to get the next page. History contains confirmed executions; use `getStatus()` for pending or failed submissions. # Transfer Assets > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/guides/transactions/transfer-assets Send native tokens or ERC-20 tokens from your account. Use `executions.execute()` to transfer assets. The examples below send ETH and an ERC-20 token on **Base Sepolia**. ## Before You Start [#before-you-start] Set up [authentication](https://namera.ai/docs/sdk/authentication) and choose an [account and session key](https://namera.ai/docs/sdk/accounts-and-session-keys). The key must be installed on Base Sepolia and allow the transfer. Fund the account with the asset you want to send. ```sh npm install @namera-ai/sdk viem ``` Replace the example account ID, session-key ID, and recipient with your own: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY! }); const walletId = "0199dfe1-0000-7000-8000-000000000001"; const sessionKeyId = "0199dfe1-0000-7000-8000-000000000002"; const recipient = "0x2222222222222222222222222222222222222222"; ``` Choose one of the transfer examples below and add it after this setup. ## Transfer Native Tokens [#transfer-native-tokens] This sends **0.001 test ETH**. Allow the recipient and a native-token allowance that covers the transfer in your session key's permissions. ```ts title="index.ts" import { parseEther } from "viem"; const transfer = await namera.executions.execute({ namespace: "eip155", walletId, sessionKeyId, chainId: "eip155:84532", calls: [{ to: recipient, value: parseEther("0.001"), data: "0x" }], sponsor: true, }); if (!transfer.success) throw new Error(transfer.error.message); console.log(transfer.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
## Transfer ERC-20 Tokens [#transfer-erc-20-tokens] Call the token contract's `transfer` function. This example sends **1 token** with **6 decimals**. Replace the token address and decimals with those of your token on Base Sepolia. The session key must allow that token transfer. ```ts title="index.ts" import { encodeFunctionData, erc20Abi, parseUnits } from "viem"; const tokenAddress = "0x3333333333333333333333333333333333333333"; const decimals = 6; const tokenTransfer = await namera.executions.execute({ namespace: "eip155", walletId, sessionKeyId, chainId: "eip155:84532", calls: [ { to: tokenAddress, value: 0n, data: encodeFunctionData({ abi: erc20Abi, functionName: "transfer", args: [recipient, parseUnits("1", decimals)], }), }, ], sponsor: true, }); if (!tokenTransfer.success) throw new Error(tokenTransfer.error.message); console.log(tokenTransfer.data); ```
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000011", "status": "prepared", "userOperationHash": "0x2222222222222222222222222222222222222222222222222222222222222222" } ```
`to` is the token contract; the recipient and amount are encoded in `data`. `value: 0n` means the call sends no native ETH. Sponsorship covers gas, not the assets being sent. Your account must hold the ETH or tokens you are transferring. These are illustrative submission values. Use the `submissionId` returned by your request to [track the transaction](https://namera.ai/docs/sdk/guides/transactions/track-transactions). `prepared` means queued, not confirmed. # Handling Results and Errors > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/handling-results-and-errors Read SDK results, handle failures, and check transaction outcomes. SDK requests return a result with `success`, `data`, and `error`. Check `success` before using the response data. ## Read a Result [#read-a-result] ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); const wallets = await namera.wallets.list(); if (wallets.success) { console.log(wallets.data); } else { console.error(wallets.error.message); } ``` On success, `data` contains the response and `error` is `null`. On failure, `data` is `null` and `error` describes what went wrong. ## Handle an API Error [#handle-an-api-error] Use `error.kind` to identify the category. For API errors, `error.cause` retains the endpoint's typed error details. For example, a rate-limit error includes the number of seconds to wait: ```ts title="index.ts" const sessions = await namera.sessionKeys.list(); if (sessions.success) { console.log(sessions.data); } else if (sessions.error.kind === "api" && sessions.error.cause._tag === "RateLimitExceeded") { console.error(`Try again in ${sessions.error.cause.retryAfterSeconds} seconds.`); } else { console.error(sessions.error.message); } ``` ### Error Categories [#error-categories] - **`api`**: Namera rejected the request. Check `cause` and, when provided, `code` for the specific reason. - **`contract`**: an input or response does not match the expected schema. Check IDs and request fields; if the inputs are valid, check your SDK version. - **`network`**: the API could not be reached. Check connectivity before retrying. - **`signer`**: signing could not proceed or a prepared operation failed validation. Follow the error message; do not bypass validation. - **`unexpected`**: another failure occurred. Keep the error details for diagnosis. Use error tags or codes for program logic, not message text. `error.status` can be `null`, including for API errors. ## Check the Transaction Outcome [#check-the-transaction-outcome] A successful `execute()` request does not mean the transaction is confirmed. Use its `submissionId` to check progress. Replace the example ID with the one returned by your execution: ```ts title="index.ts" const status = await namera.executions.getStatus("0199dfe1-0000-7000-8000-000000000003"); if (!status.success) throw new Error(status.error.message); console.log(status.data); if (status.data.status === "confirmed") { console.log(status.data.execution); } ``` Check the same submission after a short delay while its status is `reserved`, `prepared`, or `submitted`. Stop polling on `confirmed` or `failed`. ## Retry Carefully [#retry-carefully] The execution flow already retries transient preparation and completion failures using the same operation. It does not retry policy denials. Calling `execute()` again starts a new operation. Once you have a submission ID, check that submission instead of resending the transaction. A network failure alone does not prove that nothing was submitted. For a complete transaction walkthrough, see [Getting Started](https://namera.ai/docs/sdk/getting-started). # Overview > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk Build with Namera in TypeScript. The Namera SDK lets your backend provision accounts and session keys with explicit workspace permissions, then send transactions and sign within session authority. ## Quick Examples [#quick-examples] Create a client with your API key: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ### Create an Account [#create-an-account] With an API key explicitly granted `wallet:create`: ```ts title="index.ts" const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Backend treasury" }, owner: { type: "namera-managed", provider: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` Continue with [session creation and explicit installation](https://namera.ai/docs/sdk/guides/accounts/create-session-keys). ### List Accounts [#list-accounts] ```ts title="index.ts" const result = await namera.wallets.list(); if (result.success) { console.log(result.data); } ``` ### Sign a Message [#sign-a-message] Use the `session` selected in [Getting Started](https://namera.ai/docs/sdk/getting-started#list-session-keys). ```ts title="index.ts" const result = await namera.sign({ namespace: "eip155", walletId: session.walletId, sessionKeyId: session.id, chainId: "eip155:84532", type: "message", message: "Hello from Namera", }); if (result.success) { console.log(result.data); } ``` The session needs onchain signature authority and an API signature policy that allows this message on Base Sepolia. ### Execute a Transaction [#execute-a-transaction] Use the `session` selected in [Getting Started](https://namera.ai/docs/sdk/getting-started#list-session-keys). Replace the example recipient with the wallet allowed by that key. This sends 0.001 test ETH on Base Sepolia. ```ts title="index.ts" import { parseEther } from "viem"; const result = await namera.executions.execute({ namespace: "eip155", walletId: session.walletId, sessionKeyId: session.id, chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (result.success) { console.log(result.data.submissionId); } ``` Follow [Getting Started](https://namera.ai/docs/sdk/getting-started#execute-a-transaction) for funding, permissions, and checking the submission status. ## What You Can Build [#what-you-can-build] ## Start Building [#start-building] [Install the SDK](https://namera.ai/docs/sdk/installation), then follow [Getting Started](https://namera.ai/docs/sdk/getting-started) to connect your workspace. # Installation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/installation Add the Namera SDK to your project. ## Requirements [#requirements] Use **Node.js 24.14+**, or a modern browser with Fetch and Web Crypto. ## Install [#install] ```sh npm install @namera-ai/sdk ``` ```sh pnpm add @namera-ai/sdk ``` ```sh yarn add @namera-ai/sdk ``` ```sh bun add @namera-ai/sdk ``` Continue to [Getting Started](https://namera.ai/docs/sdk/getting-started) to create a client and make your first request. # Permissions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/permissions Understand what your session key is allowed to execute and sign. A valid credential is only the first requirement. Your application also needs access to a session key whose permissions allow execution or signing. Workspace management is a separate, explicitly issued authority. ## Workspace management permissions [#workspace-management-permissions] In **Settings β†’ Workspace β†’ API keys**, explicitly select the permissions your backend needs. Existing keys have none. Permissions cover all existing and future accounts and sessions in the key’s workspace, never another workspace. | Permission | Allows | | ----------------------- | --------------------------------------------------------------- | | `wallet:read` | Read all workspace accounts and their public owner descriptors. | | `wallet:create` | Create managed or passkey-owned accounts. | | `session-key:read` | Read all workspace sessions and this actor’s owner operations. | | `session-key:create` | Create sessions on any workspace account. | | `session-key:install` | Explicitly approve a stored session installation. | | `session-key:uninstall` | Explicitly approve removal of a network installation. | | `session-key:revoke` | Revoke a session’s Namera access and grants. | Only users holding the corresponding management authority may issue it. Keys do not inherit their creator’s complete role and cannot issue other keys or expand their own permissions. Create a replacement key to change permissions. A key with session creation and installation authority can grant itself full control of managed accounts. Reserve these permissions for trusted backend wallet administration. API-key permission does not replace a passkey owner’s signature. Creating a session grants its creating API-key actor access; management access alone does not grant execution access to pre-existing sessions. Passkey registration also requires an exact application origin allowlisted at key issuance. Keep the API key on your authenticated backend and bind ceremonies and operation approvals to your application users. See [account management guides](https://namera.ai/docs/sdk/guides/accounts/create-accounts). ## What Allows a Transaction [#what-allows-a-transaction] Before executing, check that: - Your API key or OAuth authorization has a grant to the selected session key. - The key is active and its installation is confirmed on the target network. - The installation is within its validity period and allows the recipient, contract calls, and amounts you want to use. Configure these in the [Namera dashboard](https://dashboard.namera.ai). For a **0.001 ETH** transfer, allow the recipient and a native-token allowance that covers the transfer, then approve the installation on that network. ## Onchain Permissions and API Policies [#onchain-permissions-and-api-policies] **Onchain permissions** are approved by the account owner and enforced by the account's contracts. They define transaction authority, including allowed targets, functions, spending allowances, and validity periods. **API policies** govern delegated signatures through Namera: signature type, allowed networks, and validity windows. Transaction spending and gas restrictions come from installed onchain permissions. All applicable policies must pass; one policy cannot override another denial. An API policy cannot allow a transaction that the onchain permissions reject. API policies apply to requests through Namera, not calls made outside it. ## Inspect a Session Key [#inspect-a-session-key] Replace the example ID with the session key you plan to use: ```ts title="index.ts" import { NameraClient } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); const result = await namera.sessionKeys.get("0199dfe1-0000-7000-8000-000000000002"); if (!result.success) throw new Error(result.error.message); const session = result.data; console.log(result.data); ``` Read `policies` for API restrictions. Each entry in `installations` includes its `chainId`, `status`, and approved `authorization`. A usable installation has status `installed`; also check its validity period and permissions. ## Check a Call Before Sending [#check-a-call-before-sending] Install `viem` if you have not already, then simulate with the same account, session key, network, and calls you intend to execute: ```sh npm install viem ``` ```ts title="index.ts" import { parseEther } from "viem"; const simulation = await namera.executions.simulate({ namespace: "eip155", walletId: session.walletId, sessionKeyId: session.id, chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], }); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ``` Replace the recipient with the address allowed by your key. Simulation does not submit a transaction or reserve billing allowance. Review the call results; balances, installed permissions and available allowance can change before execution. ## Message and Typed Data Signing [#message-and-typed-data-signing] Signing needs explicit signature authority in the installation (`allowSignatures`) and an API signature policy permitting the requested type: `message` or `typed-data`. Transaction permissions alone do not enable signing. Typed-data policies can restrict the chain, verifying contract, primary type, and domain. They do not limit the amounts inside a signed message. Transaction spending limits and expiry do not constrain onchain signature authority. Uninstall that authority onchain to revoke it. Next, choose a [supported network](https://namera.ai/docs/sdk/supported-networks). # wallets.create > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/accounts/create-account Create a 1Claw-managed or passkey-owned smart account. `namera.wallets.create()` create a 1Claw-managed or passkey-owned smart account. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Provisioned account" }, owner: { type: "namera-managed", provider: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 the complete account, including its ID, address, public owner descriptor, reconstruction data, and timestamps.
```json { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "metadata": { "version": 1, "name": "Provisioned account" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000008", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:39:05.250Z", "updatedAt": "2026-10-15T02:39:05.250Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x52e7f17258368d7f9Ebd7bDf8d6869Bc4759aBA1", "salt": "0" } } ```
## Parameters [#parameters] ### namespace [#namespace] Type: `"eip155"`. Required. The implemented chain namespace. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.create({ namespace: "eip155", // [!code focus] metadata: { version: 1, name: "Provisioned account" }, owner: { type: "namera-managed", provider: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### metadata [#metadata] Type: `object`. Required. Account display metadata. `version` is `1`; `name` identifies the account in the dashboard. Optional `description` and `logo` follow the account metadata schema. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Provisioned account" }, // [!code focus] owner: { type: "namera-managed", provider: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### owner [#owner] Type: `object`. Required. Select the account owner. Managed owners use `{ type: "namera-managed", provider: "1claw" }`. Passkey owners use `{ type: "passkey", verificationId, response }` from a registration ceremony initiated by this credential. See the [account creation guide](https://namera.ai/docs/sdk/guides/accounts/create-accounts). ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Provisioned account" }, owner: { type: "namera-managed", provider: "1claw" }, // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` For a passkey owner, your authenticated backend calls this function with its stored verification ID and the browser’s registration response: ```ts title="index.ts" import { namera } from "./client"; import type { CreateWalletRequest } from "@namera-ai/sdk"; export async function createPasskeyAccount( verificationId: string, response: Extract["response"], ) { const result = await namera.wallets.create({ namespace: "eip155", metadata: { version: 1, name: "Customer account" }, owner: { type: "passkey", verificationId, response }, // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); } ``` #### owner.verificationId [#ownerverificationid] Type: `string`. Required for passkey ownership. The one-time registration ID returned by `wallets.createPasskeyRegistrationOptions()`. Keep it bound to your authenticated application user on your backend. #### owner.response [#ownerresponse] Type: `PasskeyRegistrationResponse`. Required for passkey ownership. The browser’s complete WebAuthn registration response. Namera verifies the challenge, origin, RP ID, expiry, and initiating actor. ## Behavior and errors [#behavior-and-errors] The API key needs `wallet:create`. Accounts belong to the credential’s workspace. API keys do not gain account owner signing authority from creation alone. Managed creation retries transient failures with one SDK-generated idempotency key; a new method call starts a new request. Passkey creation is not automatically retried because registration is single-use. Creation does not deploy the smart account or install sessions. Billing limits and provider availability still apply. `MANAGEMENT_PERMISSION_DENIED` indicates authority was removed before admission. A provider result that requires recovery must not be blindly retried as a new request. # wallets.createPasskeyRegistrationOptions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/accounts/create-passkey-registration-options Start a one-time passkey account registration. `namera.wallets.createPasskeyRegistrationOptions()` start a one-time passkey account registration. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.createPasskeyRegistrationOptions({ origin: "https://app.example.com", user: { name: "Customer", displayName: "Customer" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 `verificationId`, browser-ready WebAuthn `options`, and `expiresAt`. The credential’s allowed origin determines the RP ID.
```json { "verificationId": "0199dfe1-0000-7000-8000-000000000022", "options": { "challenge": "OuAZdeWe1cPGP8if-E91tdEwtCgFVy68KEuEyXdtaIY", "rp": { "id": "app.example.com", "name": "Namera" }, "user": { "id": "MDFhMTNkNmQtNzZkYi03NTUzLWE4M2QtMTFhMzRkNWJhNjFm", "name": "Customer", "displayName": "Customer" }, "pubKeyCredParams": [ { "alg": -7, "type": "public-key" } ], "timeout": 300000, "excludeCredentials": [], "authenticatorSelection": { "residentKey": "required", "requireResidentKey": true, "userVerification": "required" }, "hints": [], "attestation": "none", "extensions": { "credProps": true } }, "expiresAt": "2026-10-15T02:44:06.347Z" } ```
## Parameters [#parameters] ### origin [#origin] Type: `string`. Required. Exact origin of the application where the browser creates the credential. A human must approve it in this API key’s passkey-origin allowlist when issuing the key. HTTPS is required except HTTP localhost/127.0.0.1 development origins. Paths, query strings, fragments, and credentials are rejected. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.createPasskeyRegistrationOptions({ origin: "https://app.example.com", // [!code focus] user: { name: "Customer", displayName: "Customer" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### user [#user] Type: `object`. Required. Application user labels for the browser prompt. `name` and `displayName` must be nonempty strings. These labels are not Namera membership or authorization. Your backend must bind the ceremony to its own authenticated application user. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.createPasskeyRegistrationOptions({ origin: "https://app.example.com", user: { name: "Customer", displayName: "Customer" }, // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Behavior and errors [#behavior-and-errors] Requires `wallet:create` and an allowlisted origin. Keep the API key on your backend; send only the registration options to the browser. Ceremonies from the same API key are independent, so multiple application users can register concurrently. Registration preparation is not automatically retried. The response does not create an account; submit the browser response through `wallets.create()`. Never accept an arbitrary verification ID from a different application user. # Get Account > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/accounts/get-account Read one account by its ID. `namera.wallets.get(walletId)` returns an account available to your credential. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.get("0199dfe1-0000-7000-8000-000000000001"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`id`** (`string`): Account ID. - **`organizationId`** (`string`): Owning organization ID. - **`metadata`** (`object`): version and name, with optional logo and description. - **`status`** (`"active" | "frozen" | "archived"`): Account lifecycle status. - **`namespace`** (`"eip155"`): Chain namespace. - **`address`** (`` `0x${string}` ``): Smart-account address. - **`owner`** (`object`): Public signing-key identity, custody, algorithm, and provider-specific protection details. - **`implementation`** (`"alchemy-modular-v2"`): Smart-account implementation. - **`data`** (`object`): Account configuration, discriminated by validatorType and accountMode. Includes deployment and version fields. - **`createdAt`** (`DateTime.Utc`): Creation time. - **`updatedAt`** (`DateTime.Utc`): Last update time. ### Example Response [#example-response]
```json { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" } ```
## Parameters [#parameters] ### walletId [#walletid] - **Type:** `string` - **Required** The account UUID returned by `wallets.list()` or `wallets.get()`. Pass its `id`, not its onchain `address`. The account must be accessible to the client’s credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.get("0199dfe1-0000-7000-8000-000000000001"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Errors [#errors] `WALLET_NOT_FOUND` means the account does not exist or is not available to your credential. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for authentication, transport, and contract errors. # wallets.getPasskeyOwner > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/accounts/get-passkey-owner Read the public passkey owner descriptor. `namera.wallets.getPasskeyOwner()` read the public passkey owner descriptor. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.getPasskeyOwner("0199dfe1-0000-7000-8000-000000000004"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 `walletId` and `owner`. Managed accounts return `owner: null`. A passkey descriptor includes signing-key ID, uncompressed public key, credential ID, RP ID, and origin; it contains no signing capability.
```json { "walletId": "0199dfe1-0000-7000-8000-000000000004", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000016", "publicKeyHex": "0x0411111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "credentialId": "dGVzdA", "rpId": "app.example.com", "origin": "https://app.example.com" } } ```
## Parameters [#parameters] ### walletId [#walletid] Type: `string`. Required. Account UUID, not its address. Obtain it from account creation or listing. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.getPasskeyOwner("0199dfe1-0000-7000-8000-000000000004"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Behavior and errors [#behavior-and-errors] Requires `wallet:read` for workspace-wide API-key access. `WALLET_NOT_FOUND` means the account is missing or outside the workspace. Use the descriptor together with independently reviewed account and installation configuration when validating a passkey approval. # List Accounts > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/accounts/list-accounts Read the accounts available to your credential. `namera.wallets.list()` returns accounts reachable through active session grants, or all workspace accounts when the API key has explicit `wallet:read` permission. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.wallets.list(); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. An array of complete records. An empty array means no matching resources are available. The method is not paginated. - **`id`** (`string`): Account ID. - **`organizationId`** (`string`): Owning organization ID. - **`metadata`** (`object`): version and name, with optional logo and description. - **`status`** (`"active" | "frozen" | "archived"`): Account lifecycle status. - **`namespace`** (`"eip155"`): Chain namespace. - **`address`** (`` `0x${string}` ``): Smart-account address. - **`owner`** (`object`): Public signing-key identity, custody, algorithm, and provider-specific protection details. - **`implementation`** (`"alchemy-modular-v2"`): Smart-account implementation. - **`data`** (`object`): Account configuration, discriminated by validatorType and accountMode. Includes deployment and version fields. - **`createdAt`** (`DateTime.Utc`): Creation time. - **`updatedAt`** (`DateTime.Utc`): Last update time. ### Example Response [#example-response]
```json [ { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" } ] ```
## Parameters [#parameters] None. `wallets.list()` does not accept filters or pagination options. ## Errors [#errors] API failures return `success: false`. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for authentication, transport, and contract errors. # Get Current Actor > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/authentication/get-current-actor Inspect the identity, organization, and grants behind your credential. `namera.auth.currentActor()` returns the actor authenticated by the client's credential. Use it to check which organization, management permissions, and session-key grants your integration is using. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.auth.currentActor(); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. The successful data is a discriminated union with `type` and `data` fields. Check `type` before reading credential-specific fields. - **`type`** (`"api-key" | "cli" | "mcp" | "user"`): Authenticated actor kind. API keys return `"api-key"`; OAuth authorizations return `"cli"` or `"mcp"` according to the authorizing client. The shared API contract also includes `"user"` for authenticated user sessions. - **`data.actorId`** (`string`): Durable actor identity, distinct from the API key or OAuth authorization ID. ### API Key and OAuth Actors [#api-key-and-oauth-actors] These actor kinds share the following fields: - **`data.organizationId`** (`string`): Organization the credential belongs to. - **`data.organizationName`** (`string | undefined`): Organization display name, when available. Use the ID rather than the name to identify the organization. - **`data.grants`** (`array`): Session-key grants available to the actor. Each entry contains a `grant` record and its `sessionKey` record. An empty array means there are no delegated execution/signing grants to use. API-key management permissions can independently authorize workspace management. - **`data.grants[].grant`** (`object`): Grant ID, organization ID, actor ID, session-key ID, granting actor ID, creation time, and nullable revocation time and revoking actor ID. - **`data.grants[].sessionKey`** (`object`): Session-key ID, organization and account IDs, signing-key ID, creating actor ID, metadata, namespace, policies, policy hash, lifecycle status, creation time, and nullable revocation fields. This is the session record, not the expanded installation and signer view returned by [Get Session Key](https://namera.ai/docs/sdk/reference/session-keys/get-session-key). For `"api-key"`, **`data.apiKey`** contains `id`, `metadata`, `keyStart`, `permissions`, `passkeyOrigins`, `expiresAt`, `lastUsedAt`, and `createdAt`. `permissions` lists explicitly issued workspace management capabilities; `passkeyOrigins` lists approved application origins. `keyStart` is a display prefix, not the secret key. Expiry and last-use times can be `null`. For `"cli"` and `"mcp"`, **`data.authorization`** contains `id`, `clientId`, `scopes`, `metadata`, `expiresAt`, `lastUsedAt`, and `createdAt`. OAuth scopes and session-key grants are separate restrictions; a grant does not bypass scopes. For `"user"`, **`data`** contains `actorId`, `session`, `user`, `organization`, `member`, and `role` instead of delegated grants and credential metadata. ### Example Response [#example-response] An API-key actor with one session-key grant:
```json { "type": "api-key", "data": { "actorId": "0199dfe1-0000-7000-8000-000000000014", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationName": "Example workspace", "grants": [ { "grant": { "id": "0199dfe1-0000-7000-8000-000000000013", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "actorId": "0199dfe1-0000-7000-8000-000000000014", "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002", "grantedByActorId": "0199dfe1-0000-7000-8000-000000000015", "revokedAt": null, "revokedByActorId": null, "createdAt": "2026-10-11T09:00:00.000Z" }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "createdByActorId": "0199dfe1-0000-7000-8000-000000000015", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "SDK test session" }, "policyHash": "0x3333333333333333333333333333333333333333333333333333333333333333", "status": "active", "revokedAt": null, "revokedByActorId": null, "createdAt": "2026-10-11T09:00:00.000Z", "namespace": "eip155", "policies": [ { "id": "0199dfe1-0000-7000-8000-000000000016", "appliesTo": "signature", "type": "evm.chain-allowlist", "version": 1, "chainIds": ["eip155:84532"] } ] } } ], "apiKey": { "permissions": [], "passkeyOrigins": [], "id": "0199dfe1-0000-7000-8000-000000000017", "metadata": { "version": 1, "name": "Example integration", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "SDK test credential" }, "keyStart": "example-prefix", "expiresAt": null, "lastUsedAt": "2026-10-11T09:10:00.000Z", "createdAt": "2026-10-11T09:00:00.000Z" } } } ```
## Parameters [#parameters] None. Authentication comes from the [client configuration](https://namera.ai/docs/sdk/reference/client/namera-client). The method cannot look up a different actor by ID. ## Check the Actor Type [#check-the-actor-type] Narrow the response before accessing grants. A grant describes delegated access; execution still requires an active session installed on the selected network and policies that allow the operation. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.auth.currentActor(); if (!result.success) throw new Error(result.error.message); const actor = result.data; if (actor.type === "api-key") { console.log(actor.data.grants); } ``` ## Errors [#errors] Invalid, expired, or revoked credentials return `success: false`. This read does not create grants or refresh an OAuth token. If you use `getAccessToken`, your callback supplies the token for the request. The SDK does not automatically retry this method. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for error inspection and [Authentication](https://namera.ai/docs/sdk/authentication) for credential setup. # NameraClient > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/client/namera-client Create and configure the Namera SDK client. `new NameraClient(config)` creates a client. Construction does not authenticate or send an API request. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const accounts = await namera.wallets.list(); if (!accounts.success) throw new Error(accounts.error.message); console.log(accounts.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] A `NameraClient` instance. Creating it does not make a network request. - **`wallets`** (`WalletClient`): list() and get(walletId). - **`sessionKeys`** (`SessionKeyClient`): list(options?) and get(sessionKeyId). - **`executions`** (`ExecutionClient`): execute, simulate, getStatus, list, and get. Also exposes low-level prepare and complete. - **`sign`** (`(request: SignRequest) => Promise`): Sign a message or typed data. - **`verifySignature`** (`(request: VerifySignatureRequest) => Promise`): Verify a smart-account signature. - **`signatures`** (`SignatureClient`): Advanced prepare and complete transport, plus sign. - **`auth`** (`AuthClient`): Read the authenticated actor with currentActor(). ## Parameters [#parameters] Pass a `NameraClientConfig` object. Exactly one of `apiKey`, `accessToken`, or `getAccessToken` is required. ### apiKey [#apikey] - **Type:** `string` - **Optional** Authenticates server-side requests using the `x-api-key` header. Keep API keys out of browser bundles and source control. Do not combine this with an OAuth option. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, // [!code focus] }); ``` ### accessToken [#accesstoken] - **Type:** `string` - **Optional** The OAuth token used for requests. Pass only the token; the SDK adds the `Bearer` prefix. Use `getAccessToken` if your application needs to supply refreshed tokens. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ accessToken: process.env.NAMERA_ACCESS_TOKEN!, // [!code focus] }); ``` ### getAccessToken [#getaccesstoken] - **Type:** `() => Promise` - **Optional** An asynchronous token supplier invoked when requests need authentication. It must resolve to a token string. Your application owns refresh and storage. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ getAccessToken: async () => process.env.NAMERA_ACCESS_TOKEN!, // [!code focus] }); ``` Replace this environment lookup with your application’s token store or refresh flow. ### baseUrl [#baseurl] - **Type:** `string` - **Optional** - **Default:** `https://api.namera.ai` The API deployment to connect to. Omit for Namera’s hosted API. Use another URL only for an alternative deployment; do not include endpoint paths or credentials. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, baseUrl: "http://localhost:8080", // [!code focus] }); ``` ### fetch [#fetch] - **Type:** `NameraFetch` - **Optional** - **Default:** `platform fetch` Overrides the Fetch implementation used for HTTP requests. Preserve the supplied request and authentication headers when wrapping it. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, fetch: (input, init) => globalThis.fetch(input, init), // [!code focus] }); ``` ### maxGasCostWei [#maxgascostwei] - **Type:** `bigint` - **Optional** Maximum approved gas cost in wei for a self-funded operation. Set before executing with `sponsor: false`. This is a ceiling, not a gas price or an extra payment; preparations above it are rejected. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; import { parseEther } from "viem"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, maxGasCostWei: parseEther("0.0001"), // [!code focus] }); ``` Install `viem` for `parseEther`. Applies to managed and automatically resolved local executions. Custom signers use their own fee ceiling. ### localSigning [#localsigning] - **Type:** `false` - **Optional** Set to `false` to prevent automatic Node.js key-store access. Omitting this option enables resolution for imported local keys. It does not disable an explicit `resolveSessionSigner`. ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, localSigning: false, // [!code focus] }); ``` ### resolveSessionSigner [#resolvesessionsigner] - **Type:** `ResolveSessionSigner` - **Optional** Overrides resolution for applications with their own key store. Returns a `LocalSessionSigner` with a trusted `binding`, `signMessage`, optional `signTypedData`, and optional `maxGasCostWei`. Use owner-reviewed configuration for the binding, never the preparation response. Signature operations require a typed-data callback and approved signature authority. Standard Node.js integrations using imported keys can omit this option. ## Result Handling [#result-handling] API methods return `NameraResult`. Check `success` before reading `data`. On success `error` is null; on failure `data` is null. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors). ## Advanced Signing [#advanced-signing] Node.js resolves imported local session keys automatically. An explicit resolver takes precedence. Browser bundles do not include native key storage. Prefer `execute()` and `sign()` over low-level prepare and complete methods, whose callers must independently validate what they sign. # Execute > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/executions/execute Prepare, authorize, and submit one or more EVM calls. `namera.executions.execute(request)` validates and signs the prepared operation, then queues it for broadcast. Each invocation starts a new submission. ## Usage [#usage] Install `@namera-ai/sdk` and `viem`. Replace the example IDs and recipient with your own. The selected session must permit these calls on Base Sepolia. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`namespace`** (`"eip155"`): Chain namespace. - **`submissionId`** (`string`): ID to pass to executions.getStatus(). - **`status`** (`"prepared" | "submitted" | "confirmed" | "failed"`): Current submission state. Prepared is queued, not confirmed. - **`userOperationHash`** (`` `0x${string}` ``): ERC-4337 user-operation hash, not a transaction hash. ### Example Response [#example-response]
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "prepared", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
## Parameters [#parameters] Pass an `ExecuteRequest` object. Fields below are required unless marked optional. ### namespace [#namespace] - **Type:** `"eip155"` - **Required** The blockchain namespace. Use `"eip155"` for every currently supported Namera network. This is not a chain ID; select the specific network with `chainId`. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", // [!code focus] walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` ### walletId [#walletid] - **Type:** `string` - **Required** The account UUID returned by `wallets.list()` or `wallets.get()`. Pass its `id`, not its onchain `address`. The account must be accessible to the client’s credential. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` ### sessionKeyId [#sessionkeyid] - **Type:** `string` - **Required** The session-key UUID returned by `sessionKeys.list()` or `sessionKeys.get()`. This identifies the delegated session, not its signing key or network installation. Execution and signing require an active grant for this key. Management reads may instead use explicit workspace `session-key:read` permission. For execution or signing, choose a key belonging to `walletId` with a confirmed installation on `chainId` and permissions that allow the requested operation. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", // [!code focus] chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` ### chainId [#chainid] - **Type:** `SupportedEvmChainId` - **Required** The target network in CAIP-2 format. For Base Sepolia, use `"eip155:84532"`, not `84532` or `"84532"`. Use the network on which the account will execute, sign, or verify the payload. The SDK restricts this field to the [supported network IDs](https://namera.ai/docs/sdk/supported-networks). Network availability is also checked by the API. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", // [!code focus] calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` ### calls [#calls] - **Type:** `readonly { to: EthereumAddress; value: bigint; data: Hex }[]` - **Required** One or more EVM calls, in execution order. Every call uses the same account, network, and session key. Supply all three fields on each call; there are no implicit values for `value` or `data`. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), // [!code focus] data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` #### calls.to [#callsto] - **Type:** `EthereumAddress` (`` `0x${string}` ``) - **Required** The 20-byte recipient or contract address. Native transfers target the recipient; contract calls target the contract, not the recipient encoded in its arguments. The session’s permissions must allow this target. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", // [!code focus] value: parseEther("0.001"), data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` #### calls.value [#callsvalue] - **Type:** `bigint` - **Required** The native-token amount in wei. Use `parseEther("0.001")` for 0.001 ETH or `0n` for a call that sends no native tokens. Negative amounts are rejected. ERC-20 amounts belong in encoded calldata, not this field. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), // [!code focus] data: "0x", }, ], sponsor: true, }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` #### calls.data [#callsdata] - **Type:** `Hex` (`` `0x${string}` ``) - **Required** The encoded contract call. Use `"0x"` for a native transfer. For contract functions, use viem’s `encodeFunctionData`; the SDK does not accept `abi`, `functionName`, or `args` directly in a call. ```ts title="index.ts" import { namera } from "./client"; import { encodeFunctionData, erc20Abi, parseUnits } from "viem"; const result = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x3333333333333333333333333333333333333333", value: 0n, data: encodeFunctionData({ // [!code focus:5] abi: erc20Abi, functionName: "transfer", args: ["0x2222222222222222222222222222222222222222", parseUnits("1", 6)], }), }, ], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` This encodes a transfer of one token with six decimals. Use your token’s actual decimals and pass its contract address as `to`. ### sponsor [#sponsor] - **Type:** `boolean` - **Optional** - **Default:** `true` Sponsorship covers gas, not transferred assets, and remains subject to workspace allowances and policies. Set `false` to pay from the account. Fund both the transfer and gas, and configure [maxGasCostWei](https://namera.ai/docs/sdk/reference/client/namera-client#maxgascostwei). A custom signer must carry its own fee ceiling. See [Sponsor Gas](https://namera.ai/docs/sdk/guides/transactions/sponsor-gas) for a complete self-funded example. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.execute({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], sponsor: true, // [!code focus] }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` ## Behavior [#behavior] Use [Get Submission Status](https://namera.ai/docs/sdk/reference/executions/get-submission-status) to track this submission. Do not call execute again to poll. Internal preparation retries reuse one idempotency key; completion retries reuse the same submission. ## Errors [#errors] Policy, authorization, billing, and execution failures return `success: false`. Prepared-operation validation failures use `kind: "signer"`. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for authentication, transport, and contract errors. Guide: [Transfer Assets](https://namera.ai/docs/sdk/guides/transactions/transfer-assets). # Get Execution > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/executions/get-execution Read a confirmed execution, receipt, and related resources. `namera.executions.get(executionId)` returns the full confirmed record. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.get("0199dfe1-0000-7000-8000-000000000012"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`execution`** (`ExecutionResponse`): id, executionSubmissionId, organizationId, sessionKeyGrantId, namespace, data, and createdAt. - **`execution.data`** (`EvmExecutionData`): version, namespace, chainId, calls, userOperationHash, transactionHash, and receipt. - **`execution.data.receipt`** (`SuccessfulEvmExecutionReceipt`): Successful user-operation receipt including block, gas, sender, and EntryPoint. - **`wallet`** (`WalletResponse`): Complete account record. - **`sessionKey`** (`SessionKeySummaryResponse`): Session identity, metadata, policies, lifecycle, and creation fields without expanded relations. - **`actor`** (`ExecutionActorDetailsResponse`): Discriminated by type. user has member; api-key has apiKey; cli and mcp have authorization. Includes id and public credential details, never raw secrets. ### Example Response [#example-response]
```json { "execution": { "id": "0199dfe1-0000-7000-8000-000000000012", "executionSubmissionId": "0199dfe1-0000-7000-8000-000000000003", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "sessionKeyGrantId": "0199dfe1-0000-7000-8000-000000000013", "namespace": "eip155", "data": { "version": 1, "chainId": "eip155:84532", "calls": [ { "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000", "data": "0x" } ], "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "receipt": { "version": 1, "namespace": "eip155", "chainId": "eip155:84532", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "blockHash": "0x6666666666666666666666666666666666666666666666666666666666666666", "blockNumber": "32000000", "sender": "0x1111111111111111111111111111111111111111", "nonce": "0", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "paymaster": null, "actualGasCost": "0", "actualGasUsed": "120000", "success": true, "reason": null } }, "createdAt": "2026-10-11T09:10:00.000Z" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000006", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send 0.001 test ETH on Base Sepolia" }, "policies": [], "policyHash": "1111111111111111111111111111111111111111111111111111111111111111", "status": "active", "revokedAt": null, "createdAt": "2026-10-11T09:05:00.000Z" }, "actor": { "id": "0199dfe1-0000-7000-8000-000000000012", "type": "api-key", "apiKey": { "id": "0199dfe1-0000-7000-8000-000000000013", "metadata": { "version": 1, "name": "Example integration", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "SDK examples" }, "keyStart": "example", "expiresAt": null, "lastUsedAt": "2026-10-11T09:10:00.000Z", "revokedAt": null, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" } } } ```
## Parameters [#parameters] ### executionId [#executionid] - **Type:** `string` - **Required** The confirmed execution’s `id`, returned by `executions.list()` or inside the confirmed `getStatus()` execution record. Submission IDs and transaction hashes are different identifiers and cannot be used here. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.get("0199dfe1-0000-7000-8000-000000000012"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Errors [#errors] `EXECUTION_NOT_FOUND` means the confirmed record is missing or unavailable to your credential. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for shared authentication, transport, and contract errors. # Get Submission Status > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/executions/get-submission-status Read the current state of an execution submission. `namera.executions.getStatus(submissionId)` tracks a submission before and after confirmation. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.getStatus("0199dfe1-0000-7000-8000-000000000003"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`namespace`** (`"eip155"`): Chain namespace. - **`submissionId`** (`string`): Requested submission UUID. - **`status`** (`"reserved" | "prepared" | "submitted" | "confirmed" | "failed"`): Discriminator for the response shape. - **`userOperationHash`** (`` `0x${string}` | null ``): Present only for reserved, prepared, and submitted. - **`execution`** (`ExecutionResponse`): Complete confirmed execution record. Present only for confirmed. ### Pending Response [#pending-response]
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "submitted", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111" } ```
### Confirmed Response [#confirmed-response]
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "confirmed", "execution": { "id": "0199dfe1-0000-7000-8000-000000000012", "executionSubmissionId": "0199dfe1-0000-7000-8000-000000000003", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "sessionKeyGrantId": "0199dfe1-0000-7000-8000-000000000013", "namespace": "eip155", "data": { "version": 1, "chainId": "eip155:84532", "calls": [ { "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000", "data": "0x" } ], "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "receipt": { "version": 1, "namespace": "eip155", "chainId": "eip155:84532", "userOperationHash": "0x1111111111111111111111111111111111111111111111111111111111111111", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "blockHash": "0x6666666666666666666666666666666666666666666666666666666666666666", "blockNumber": "32000000", "sender": "0x1111111111111111111111111111111111111111", "nonce": "0", "entryPoint": "0x0000000071727De22E5E9d8BAf0edAc6f37da032", "paymaster": null, "actualGasCost": "0", "actualGasUsed": "120000", "success": true, "reason": null } }, "createdAt": "2026-10-11T09:10:00.000Z" } } ```
### Failed Response [#failed-response]
```json { "namespace": "eip155", "submissionId": "0199dfe1-0000-7000-8000-000000000003", "status": "failed" } ```
## Parameters [#parameters] ### submissionId [#submissionid] - **Type:** `string` - **Required** The `submissionId` returned by `execute()`. Save it to resume tracking after a restart. It is neither the confirmed execution ID nor an onchain transaction hash. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.getStatus("0199dfe1-0000-7000-8000-000000000003"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Polling [#polling] Check the same submission while its status is `reserved`, `prepared`, or `submitted`. Stop on `confirmed` or `failed`. This method performs one read; it does not poll automatically. Do not call `execute()` again to check progress. ## Errors [#errors] `EXECUTION_SUBMISSION_NOT_FOUND` means the submission is missing or unavailable to your credential. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for shared authentication, transport, and contract errors. Guide: [Track Transactions](https://namera.ai/docs/sdk/guides/transactions/track-transactions). # List Executions > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/executions/list-executions List confirmed executions with cursor pagination. `namera.executions.list(options?)` returns confirmed history. Pending submissions are not included. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.list({ walletId: "0199dfe1-0000-7000-8000-000000000001", }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`items`** (`readonly ExecutionListItemResponse[]`): Confirmed records accessible to your credential. - **`items[].details`** (`object`): id, namespace, chainId, transactionHash, and createdAt. - **`items[].wallet`** (`object`): id, namespace, address, and metadata. - **`items[].sessionKey`** (`object`): id, namespace, and metadata. - **`items[].actorType`** (`"user" | "api-key" | "mcp" | "cli"`): Submitting actor kind. - **`nextCursor`** (`string | null`): Pass as cursor for the next page; null ends pagination. ### Example Response [#example-response]
```json { "items": [ { "details": { "id": "0199dfe1-0000-7000-8000-000000000012", "namespace": "eip155", "chainId": "eip155:84532", "transactionHash": "0x5555555555555555555555555555555555555555555555555555555555555555", "createdAt": "2026-10-11T09:10:00.000Z" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" } }, "sessionKey": { "id": "0199dfe1-0000-7000-8000-000000000002", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send test ETH on Base Sepolia" } }, "actorType": "api-key" } ], "nextCursor": null } ```
## Parameters [#parameters] The optional `options` object defaults to `{}`. ### walletId [#walletid] - **Type:** `string` - **Optional** Restricts results to the account UUID, not its address. Combine with `sessionKeyId` to narrow the results further. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.list({ walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### sessionKeyId [#sessionkeyid] - **Type:** `string` - **Optional** Restricts results to confirmed executions authorized by this session. Pending submissions are excluded. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.executions.list({ sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### cursor [#cursor] - **Type:** `string` - **Optional** Use `nextCursor` from the previous page. Omit for the first page and stop when it is `null`. Preserve the same filters across pages. There is no configurable page-size parameter. ```ts title="index.ts" import { namera } from "./client"; const first = await namera.executions.list(); if (!first.success) throw new Error(first.error.message); if (first.data.nextCursor !== null) { const next = await namera.executions.list({ cursor: first.data.nextCursor, // [!code focus] }); if (!next.success) throw new Error(next.error.message); console.log(next.data); } ``` ## Errors [#errors] Invalid filter IDs return a contract error. API failures return `success: false`. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for shared authentication, transport, and contract errors. Guide: [Track Transactions](https://namera.ai/docs/sdk/guides/transactions/track-transactions). # Simulate > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/executions/simulate Simulate calls and check the selected session’s installed authority. `namera.executions.simulate(request)` does not sign, submit, or sponsor an operation. ## Usage [#usage] Install `@namera-ai/sdk` and `viem`. Replace the example IDs and recipient with your own. The selected session must permit these calls on Base Sepolia. ```ts title="index.ts" import { namera } from "./client"; import type { SimulateExecutionRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const request = { namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies SimulateExecutionRequest; const simulation = await namera.executions.simulate(request); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`namespace`** (`"eip155"`): Chain namespace. - **`walletId`** (`string`): Account UUID. - **`chainId`** (`SupportedEvmChainId`): Simulation network. - **`account`** (`` `0x${string}` ``): Smart-account address. - **`callsSucceeded`** (`boolean`): Whether the simulated calls succeeded. - **`simulation`** (`EvmIntentSimulation`): userOperation gas estimates and calls results, assetChanges, and transfers. - **`allowed`** (`boolean`): Point-in-time eligibility; not a guarantee of later execution. - **`sessionKeyId`** (`string`): Present when allowed is true. - **`denials`** (`readonly { sessionKeyId: string; policyId: string; code: EvmPolicyDenialCode }[]`): Legacy response variant retained for client compatibility; current servers return errors for failed authorization or simulation, not policy denials. ### Example Response [#example-response]
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "callsSucceeded": true, "simulation": { "userOperation": { "source": "eth_estimateUserOperationGas", "callGasLimit": "50000", "verificationGasLimit": "100000", "preVerificationGas": "50000", "maxFeePerGas": "1000000000", "maxPriorityFeePerGas": "1000000" }, "calls": { "source": "viem.simulateCalls", "results": [ { "status": "success", "returnData": "0x", "gasUsed": "21000" } ], "assetChanges": [], "transfers": [ { "callIndex": 0, "from": "0x1111111111111111111111111111111111111111", "to": "0x2222222222222222222222222222222222222222", "value": "1000000000000000" } ] } }, "allowed": true, "sessionKeyId": "0199dfe1-0000-7000-8000-000000000002" } ```
## Parameters [#parameters] Pass a `SimulateExecutionRequest` object. Simulation does not accept a `sponsor` field. ### namespace [#namespace] - **Type:** `"eip155"` - **Required** The blockchain namespace. Use `"eip155"` for every currently supported Namera network. This is not a chain ID; select the specific network with `chainId`. ```ts title="index.ts" import { namera } from "./client"; import type { SimulateExecutionRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const request = { namespace: "eip155", // [!code focus] walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies SimulateExecutionRequest; const simulation = await namera.executions.simulate(request); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ``` ### walletId [#walletid] - **Type:** `string` - **Required** The account UUID returned by `wallets.list()` or `wallets.get()`. Pass its `id`, not its onchain `address`. The account must be accessible to the client’s credential. ```ts title="index.ts" import { namera } from "./client"; import type { SimulateExecutionRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const request = { namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies SimulateExecutionRequest; const simulation = await namera.executions.simulate(request); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ``` ### sessionKeyId [#sessionkeyid] - **Type:** `string` - **Required** The session-key UUID returned by `sessionKeys.list()` or `sessionKeys.get()`. This identifies the delegated session, not its signing key or network installation. Execution and signing require an active grant for this key. Management reads may instead use explicit workspace `session-key:read` permission. For execution or signing, choose a key belonging to `walletId` with a confirmed installation on `chainId` and permissions that allow the requested operation. ```ts title="index.ts" import { namera } from "./client"; import type { SimulateExecutionRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const request = { namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", // [!code focus] chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies SimulateExecutionRequest; const simulation = await namera.executions.simulate(request); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ``` ### chainId [#chainid] - **Type:** `SupportedEvmChainId` - **Required** The target network in CAIP-2 format. For Base Sepolia, use `"eip155:84532"`, not `84532` or `"84532"`. Use the network on which the account will execute, sign, or verify the payload. The SDK restricts this field to the [supported network IDs](https://namera.ai/docs/sdk/supported-networks). Network availability is also checked by the API. ```ts title="index.ts" import { namera } from "./client"; import type { SimulateExecutionRequest } from "@namera-ai/sdk"; import { parseEther } from "viem"; const request = { namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", // [!code focus] calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), data: "0x", }, ], } satisfies SimulateExecutionRequest; const simulation = await namera.executions.simulate(request); if (!simulation.success) throw new Error(simulation.error.message); console.log(simulation.data); ``` ### calls [#calls] - **Type:** `readonly { to: EthereumAddress; value: bigint; data: Hex }[]` - **Required** One or more EVM calls, in execution order. Every call uses the same account, network, and session key. Supply all three fields on each call; there are no implicit values for `value` or `data`. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.simulate({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), // [!code focus] data: "0x", }, ], }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` #### calls.to [#callsto] - **Type:** `EthereumAddress` (`` `0x${string}` ``) - **Required** The 20-byte recipient or contract address. Native transfers target the recipient; contract calls target the contract, not the recipient encoded in its arguments. The session’s permissions must allow this target. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.simulate({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", // [!code focus] value: parseEther("0.001"), data: "0x", }, ], }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` #### calls.value [#callsvalue] - **Type:** `bigint` - **Required** The native-token amount in wei. Use `parseEther("0.001")` for 0.001 ETH or `0n` for a call that sends no native tokens. Negative amounts are rejected. ERC-20 amounts belong in encoded calldata, not this field. ```ts title="index.ts" import { namera } from "./client"; import { parseEther } from "viem"; const execution = await namera.executions.simulate({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x2222222222222222222222222222222222222222", value: parseEther("0.001"), // [!code focus] data: "0x", }, ], }); if (!execution.success) throw new Error(execution.error.message); console.log(execution.data); ``` #### calls.data [#callsdata] - **Type:** `Hex` (`` `0x${string}` ``) - **Required** The encoded contract call. Use `"0x"` for a native transfer. For contract functions, use viem’s `encodeFunctionData`; the SDK does not accept `abi`, `functionName`, or `args` directly in a call. ```ts title="index.ts" import { namera } from "./client"; import { encodeFunctionData, erc20Abi, parseUnits } from "viem"; const result = await namera.executions.simulate({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", calls: [ { to: "0x3333333333333333333333333333333333333333", value: 0n, data: encodeFunctionData({ // [!code focus:5] abi: erc20Abi, functionName: "transfer", args: ["0x2222222222222222222222222222222222222222", parseUnits("1", 6)], }), }, ], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` This encodes a transfer of one token with six decimals. Use your token’s actual decimals and pass its contract address as `to`. ## Errors [#errors] Execution, authorization, and network failures return `success: false`. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for authentication, transport, and contract errors. Guide: [Simulate Transactions](https://namera.ai/docs/sdk/guides/transactions/simulate-transactions). # sessionKeys.approveOperation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/approve-operation Approve a prepared installation or removal. `namera.sessionKeys.approveOperation()` approve a prepared installation or removal. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.approveOperation({ operationId: "0199dfe1-0000-7000-8000-000000000014", approval: { type: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 the operation ID and durable status. `signed` means the signed request was persisted for worker submission; it does not mean the installation is confirmed.
```json { "operationId": "0199dfe1-0000-7000-8000-000000000014", "status": "signed" } ```
## Parameters [#parameters] ### operationId [#operationid] Type: `string`. Required. ID returned by preparation or recovery. It must belong to this same API-key actor. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.approveOperation({ operationId: "0199dfe1-0000-7000-8000-000000000014", // [!code focus] approval: { type: "1claw" }, }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### approval [#approval] Type: `object`. Required. Use `{ type: "1claw" }` for a managed account owner. This explicitly authorizes managed owner signing. For a passkey owner use `{ type: "passkey", response }`, where `response` is the browser’s complete assertion over the validated preparation challenge. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.approveOperation({ operationId: "0199dfe1-0000-7000-8000-000000000014", approval: { type: "1claw" }, // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` #### approval.response [#approvalresponse] Type: `PasskeyAuthenticationResponse`. Required only for `type: "passkey"`. The assertion must match the stored account credential, challenge, RP ID, origin, and counter. Keep API credentials on your backend; the browser returns only its assertion to your application. ## Behavior and errors [#behavior-and-errors] Requires the matching install/uninstall permission. Authorization is checked again before managed signing and at acceptance; revocation prevents unaccepted work from gaining authority. Only the initiating actor can approve. Transient retries reuse the same operation and exact assertion. Accepted signed work remains subject to reconciliation after API-key revocation. Validate using `validateOwnerApproval()` or `validateManagedOwnerApproval()` before this call; the SDK does not silently approve prepared calldata for you. Those helpers require independently reconstructed owner, deployment, call, and fee expectations, not values copied from the preparation. # sessionKeys.cancelOperation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/cancel-operation Cancel an unsigned installation or removal preparation. `namera.sessionKeys.cancelOperation()` cancel an unsigned installation or removal preparation. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.cancelOperation("0199dfe1-0000-7000-8000-000000000014"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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` and `status: "cancelled"`.
```json { "operationId": "0199dfe1-0000-7000-8000-000000000014", "status": "cancelled" } ```
## Parameters [#parameters] ### operationId [#operationid] Type: `string`. Required. Resource UUID returned by creation, preparation, or recovery; not an address or transaction hash. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.cancelOperation("0199dfe1-0000-7000-8000-000000000014"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Behavior and errors [#behavior-and-errors] Requires the operation’s install/uninstall permission and the initiating actor. Signed or submitted work cannot be cancelled; it must reconcile. Cancellation changes no session grants or onchain permissions. # sessionKeys.create > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/create-session-key Register a local or 1Claw-managed session signer. `namera.sessionKeys.create()` register a local or 1Claw-managed session signer. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 the complete pending session, public signer, account, creator, and per-network installations. API-key creators use `{ type: "api-key", actorId, id, metadata }`; human creators retain the member/user/role shape. This fixture uses root authority; choose narrower permissions for restricted agents.
```json { "id": "0199dfe1-0000-7000-8000-000000000003", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000012", "namespace": "eip155", "metadata": { "version": 1, "name": "Local agent" }, "policies": [], "policyHash": "9Z4ZzPfiQ4hIUpSXTY_nQ2E9-kjd2w_5wbLwIj7visI", "status": "pending", "revokedAt": null, "createdAt": "2026-10-15T02:39:05.307Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x04e37a5065266fa599595e06a6968cdfe2d588cfbbbbb48f0d4c504048c53786a87ff061f472d579833ea98e99f425febabd2445a8760e225cb1e5b4a029cd18b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000006", "metadata": { "version": 1, "name": "Provisioned account" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000008", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:39:05.250Z", "updatedAt": "2026-10-15T02:39:05.250Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x52e7f17258368d7f9Ebd7bDf8d6869Bc4759aBA1", "salt": "0" } }, "creator": { "type": "api-key", "actorId": "0199dfe1-0000-7000-8000-000000000009", "id": "0199dfe1-0000-7000-8000-000000000010", "metadata": { "version": 1, "name": "Workspace backend" } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000013", "chainId": "eip155:11155111", "status": "pending", "authorization": { "version": 1, "entityId": 142534698, "signerAddress": "0x7838CE7D0AC8943A2fAA4e8ab8ae901b05eA7A03", "permissions": [ { "type": "root" } ], "allowSignatures": false, "validAfter": 1792031945, "validUntil": 1792035545 }, "installTransactionHash": null, "uninstallTransactionHash": null } ] } ```
## Parameters [#parameters] ### namespace [#namespace] Type: `"eip155"`. Required. The implemented chain namespace. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", // [!code focus] walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### walletId [#walletid] Type: `string`. Required. Existing account UUID in the same workspace. Account ownership and session custody are independent. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### metadata [#metadata] Type: `object`. Required. Session display metadata: `version: 1`, a required `name`, and optional `description` and `logo`. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, // [!code focus] signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### signer [#signer] Type: `object`. Required. Use `{ custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }`, or `{ custody: "local", algorithm: "secp256k1", publicKey }`. The local public key must be uncompressed, beginning with `0x04` and containing 65 bytes. Keep the corresponding private key in your application’s secure signer store. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, // [!code focus] onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### onchain [#onchain] Type: `object`. Required. Contains at least one installation; each network may appear once. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { // [!code focus] installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` #### onchain.installations [#onchaininstallations] Type: `readonly object[]`. Required. Each entry specifies `chainId` (a supported CAIP-2 network ID), `validAfter` and `validUntil` (Unix seconds), `permissions` (onchain permission definitions), and optional `allowSignatures` (defaults to `false`). Expiry must follow the start time and remain in the future at admission. Amount allowances are `bigint` values in token base units. `root` grants unrestricted account authority and cannot be combined with other permissions. #### onchain.installations[].chainId [#onchaininstallationschainid] Type: `SupportedEvmChainId`. Required. The supported CAIP-2 network, such as `eip155:11155111`. Each network may appear once. #### onchain.installations[].validAfter [#onchaininstallationsvalidafter] Type: `number`. Required. Nonnegative Unix timestamp in seconds at which transaction authority begins. #### onchain.installations[].validUntil [#onchaininstallationsvaliduntil] Type: `number`. Required. Unix timestamp in seconds after `validAfter`, still in the future at admission. Each network has its own expiry. #### onchain.installations[].permissions [#onchaininstallationspermissions] Type: `readonly EvmSessionPermission[]`. Required and nonempty. Choose onchain permissions such as native-token or ERC-20 allowances, allowed contracts/functions, and gas limits. Allowances are bigint base-unit amounts, not token display units. Root authority is exclusive and unrestricted. See [Permissions](https://namera.ai/docs/sdk/permissions). #### onchain.installations[].allowSignatures [#onchaininstallationsallowsignatures] Type: `boolean`. Optional; defaults to `false`. Enables onchain ERC-1271 signature authority. Transaction spending and time hooks do not constrain existing signature authority; uninstall it to remove that authority onchain. Namera signing also requires an API signature policy. ### policies [#policies] Type: `readonly object[]`. Required. Session-level API signature policies. An empty array adds no API signature policy; transaction authority comes from installed onchain permissions. Signature use additionally requires explicit onchain signature authority. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.create({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", metadata: { version: 1, name: "Local agent" }, signer: { custody: "namera-managed", provider: "1claw", algorithm: "secp256k1" }, onchain: { installations: [ { chainId: "eip155:11155111", validAfter: Math.floor(Date.now() / 1000), validUntil: Math.floor(Date.now() / 1000) + 3600, permissions: [{ type: "root" }], allowSignatures: false, }, ], }, policies: [], // [!code focus] }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` #### policies[].type and policies[].version [#policiestype-and-policiesversion] Type: `"evm.signature" | "evm.time-window" | "evm.chain-allowlist"`, and `1`. Required for each policy. Each policy type may appear once. Creation accepts configuration only; persisted `id` and `appliesTo` fields are assigned by Namera. #### policies[].allowedTypes and policies[].typedDataRules [#policiesallowedtypes-and-policiestypeddatarules] Required for `evm.signature`: `allowedTypes` is a nonempty unique array of `"message"` and/or `"typed-data"`. Optional `typedDataRules` is a nonempty array of rules with `chainId`, `verifyingContract`, and nonempty unique `primaryTypes`; `name` and `version` optionally restrict the typed-data domain. Omit rules to allow all typed data when that signature type is enabled. Rules constrain Namera requests, not direct signing with a caller-held key. #### policies[].startsAt and policies[].expiresAt [#policiesstartsat-and-policiesexpiresat] Required for `evm.time-window`. SDK values are `DateTime.Utc | null` for `startsAt` and `DateTime.Utc` for `expiresAt`; wire values are ISO date-time strings. Null start means no lower time bound. Expiry must follow a non-null start and remain in the future at admission. This policy restricts API signatures, not installed transaction authority. #### policies[].chainIds [#policieschainids] Required for `evm.chain-allowlist`: a nonempty unique array of supported CAIP-2 network IDs on which API signing is permitted. A chain allowlist does not itself grant signature authority. ## Behavior and errors [#behavior-and-errors] Requires `session-key:create` and applies to any account in the API key’s workspace. Local signers submit only a public key. Managed signers provision a dedicated 1Claw key; never submit provider credentials. Creation atomically grants the calling API-key actor access to the new session. The session and installations remain pending until explicit owner-approved installation is confirmed. Managed creation retries transient failures with an SDK-generated idempotency key. Local registration is not automatically retried; retain your signer if a response is lost. No private key is returned. `NETWORK_PAUSED`, billing limits, invalid permissions, duplicate signers, and expired validity windows can reject creation. # sessionKeys.getActiveOperation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/get-active-operation Recover an active installation or removal operation. `namera.sessionKeys.getActiveOperation()` recover an active installation or removal operation. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.getActiveOperation({ sessionKeyId: "0199dfe1-0000-7000-8000-000000000003", chainId: "eip155:11155111", kind: "install", }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 `operation: null` when there is no active operation for this actor and target. Otherwise the operation contains `operationId`, `status`, and `preparation`. An unexpired unsigned operation returns a fresh preparation using its original internal idempotency key; signed/submitted operations have `preparation: null`. The SDK never exposes the stored retry key.
```json { "operation": { "operationId": "0199dfe1-0000-7000-8000-000000000014", "status": "awaiting-signature", "preparation": { "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" } } } ```
## Parameters [#parameters] ### sessionKeyId [#sessionkeyid] Type: `string`. Required. Session UUID. Requires session read access to resolve the installation. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.getActiveOperation({ sessionKeyId: "0199dfe1-0000-7000-8000-000000000003", // [!code focus] chainId: "eip155:11155111", kind: "install", }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### chainId [#chainid] Type: `SupportedEvmChainId`. Required. Configured CAIP-2 network ID. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.getActiveOperation({ sessionKeyId: "0199dfe1-0000-7000-8000-000000000003", chainId: "eip155:11155111", // [!code focus] kind: "install", }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ### kind [#kind] Type: `"install" | "uninstall"`. Required. The operation type you want to recover. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.getActiveOperation({ sessionKeyId: "0199dfe1-0000-7000-8000-000000000003", chainId: "eip155:11155111", kind: "install", // [!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`; recovering an unsigned preparation also requires its install/uninstall permission. API keys recover only their own operations. If `preparation` is present, review it and explicitly approve. If the operation is signed or submitted, poll it. Cancel an unsigned operation before deliberately preparing a replacement. Recovery does not create or install a new session. # sessionKeys.getOperation > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/get-operation Read the status of an installation or removal operation. `namera.sessionKeys.getOperation()` read the status of an installation or removal operation. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.getOperation("0199dfe1-0000-7000-8000-000000000014"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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` and `status`: `awaiting-signature`, `signed`, `submitted`, `confirmed`, `failed`, `expired`, or `cancelled`. Only `confirmed` establishes successful receipt confirmation.
```json { "operationId": "0199dfe1-0000-7000-8000-000000000014", "status": "confirmed" } ```
## Parameters [#parameters] ### operationId [#operationid] Type: `string`. Required. Resource UUID returned by creation, preparation, or recovery; not an address or transaction hash. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.getOperation("0199dfe1-0000-7000-8000-000000000014"); // [!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`. API keys can poll only operations initiated by that same actor. `OPERATION_UNAVAILABLE` covers missing, foreign-workspace, and other-actor operations. A missing receipt leaves an operation pending; do not start another installation simply because polling is slow. # Get Session Key > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/get-session-key Read a session key and its network installations. `namera.sessionKeys.get(sessionKeyId)` returns the key, its account, creator, and installations. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.get("0199dfe1-0000-7000-8000-000000000002"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`id`** (`string`): Session-key ID. - **`organizationId`** (`string`): Owning organization. - **`walletId`** (`string`): Account ID. - **`signingKeyId`** (`string`): Signing-key identity. - **`namespace`** (`"eip155"`): Chain namespace. - **`metadata`** (`object`): version and name, with optional logo and description. - **`policies`** (`readonly Policy[]`): Additional API policies. - **`policyHash`** (`string`): Stored policy hash. - **`status`** (`"pending" | "active" | "revoking" | "revoked"`): Session lifecycle status. - **`revokedAt`** (`DateTime.Utc | null`): Revocation time, if revoked. - **`createdAt`** (`DateTime.Utc`): Creation time. - **`signer`** (`object`): Public signer identity and custody. No private key. - **`wallet`** (`WalletResponse`): Complete account record. - **`creator`** (`object`): Human member/user/role details, or an API-key descriptor with `type`, `actorId`, `id`, and `metadata`. - **`installations`** (`readonly Installation[]`): Each has id, chainId, status, authorization, installTransactionHash, and uninstallTransactionHash. Authorization includes permissions, signature authority, and validity timestamps. ### Example Response [#example-response]
```json { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000006", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send 0.001 test ETH on Base Sepolia" }, "policies": [], "policyHash": "1111111111111111111111111111111111111111111111111111111111111111", "status": "active", "revokedAt": null, "createdAt": "2026-10-11T09:05:00.000Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000000007", "userId": "0199dfe1-0000-7000-8000-000000000008", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationRoleId": "0199dfe1-0000-7000-8000-000000000009", "joinedAt": "2026-10-11T08:00:00.000Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000000008", "email": "developer@example.com", "emailVerified": true, "metadata": { "version": 1, "name": "Example developer", "image": { "type": "emoji", "value": "πŸ‘€" } }, "lastLoginAt": "2026-10-11T08:55:00.000Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000000009", "key": "developer", "metadata": { "version": 1, "name": "Developer", "logo": { "type": "emoji", "value": "πŸ’»" }, "description": "Manage test accounts and session keys" }, "type": "custom", "permissions": [ "wallet:read", "wallet:create", "session-key:read", "session-key:create", "api-key:create" ], "systemRoleId": null } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000010", "chainId": "eip155:84532", "status": "installed", "authorization": { "version": 1, "entityId": 1, "signerAddress": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf", "permissions": [ { "type": "contract-access", "address": "0x2222222222222222222222222222222222222222" }, { "type": "native-token-transfer", "allowance": "1000000000000000" } ], "allowSignatures": false, "validAfter": 1791709200, "validUntil": 1794387600 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ```
## Parameters [#parameters] ### sessionKeyId [#sessionkeyid] - **Type:** `string` - **Required** The session-key UUID returned by `sessionKeys.list()` or `sessionKeys.get()`. This identifies the delegated session, not its signing key or network installation. Execution and signing require an active grant for this key. Management reads may instead use explicit workspace `session-key:read` permission. For execution or signing, choose a key belonging to `walletId` with a confirmed installation on `chainId` and permissions that allow the requested operation. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.get("0199dfe1-0000-7000-8000-000000000002"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Errors [#errors] `SESSION_KEY_NOT_FOUND` means the key does not exist or is not available to your credential. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for authentication, transport, and contract errors. # List Session Keys > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/list-session-keys Read authorized session keys, optionally filtered by account. `namera.sessionKeys.list(options?)` lists session keys available to your credential. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.list({ walletId: "0199dfe1-0000-7000-8000-000000000001" }); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. An array of complete records. An empty array means no matching resources are available. The method is not paginated. - **`id`** (`string`): Session-key ID. - **`organizationId`** (`string`): Owning organization. - **`walletId`** (`string`): Account ID. - **`signingKeyId`** (`string`): Signing-key identity. - **`namespace`** (`"eip155"`): Chain namespace. - **`metadata`** (`object`): version and name, with optional logo and description. - **`policies`** (`readonly Policy[]`): Additional API policies. - **`policyHash`** (`string`): Stored policy hash. - **`status`** (`"pending" | "active" | "revoking" | "revoked"`): Session lifecycle status. - **`revokedAt`** (`DateTime.Utc | null`): Revocation time, if revoked. - **`createdAt`** (`DateTime.Utc`): Creation time. - **`signer`** (`object`): Public signer identity and custody. No private key. - **`wallet`** (`WalletResponse`): Complete account record. - **`creator`** (`object`): Human member/user/role details, or an API-key descriptor with `type`, `actorId`, `id`, and `metadata`. - **`installations`** (`readonly Installation[]`): Each has id, chainId, status, authorization, installTransactionHash, and uninstallTransactionHash. Authorization includes permissions, signature authority, and validity timestamps. ### Example Response [#example-response]
```json [ { "id": "0199dfe1-0000-7000-8000-000000000002", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "walletId": "0199dfe1-0000-7000-8000-000000000001", "signingKeyId": "0199dfe1-0000-7000-8000-000000000006", "namespace": "eip155", "metadata": { "version": 1, "name": "Example session", "logo": { "type": "emoji", "value": "πŸ”‘" }, "description": "Send 0.001 test ETH on Base Sepolia" }, "policies": [], "policyHash": "1111111111111111111111111111111111111111111111111111111111111111", "status": "active", "revokedAt": null, "createdAt": "2026-10-11T09:05:00.000Z", "signer": { "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1", "publicKey": "0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000000001", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "metadata": { "version": 1, "name": "Example account", "logo": { "type": "emoji", "value": "πŸ‘›" }, "description": "SDK test account" }, "status": "active", "namespace": "eip155", "address": "0x1111111111111111111111111111111111111111", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000000005", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "7702", "delegationVersion": "v1.1.0" }, "createdAt": "2026-10-11T09:00:00.000Z", "updatedAt": "2026-10-11T09:00:00.000Z" }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000000007", "userId": "0199dfe1-0000-7000-8000-000000000008", "organizationId": "0199dfe1-0000-7000-8000-000000000004", "organizationRoleId": "0199dfe1-0000-7000-8000-000000000009", "joinedAt": "2026-10-11T08:00:00.000Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000000008", "email": "developer@example.com", "emailVerified": true, "metadata": { "version": 1, "name": "Example developer", "image": { "type": "emoji", "value": "πŸ‘€" } }, "lastLoginAt": "2026-10-11T08:55:00.000Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000000009", "key": "developer", "metadata": { "version": 1, "name": "Developer", "logo": { "type": "emoji", "value": "πŸ’»" }, "description": "Manage test accounts and session keys" }, "type": "custom", "permissions": [ "wallet:read", "wallet:create", "session-key:read", "session-key:create", "api-key:create" ], "systemRoleId": null } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000000010", "chainId": "eip155:84532", "status": "installed", "authorization": { "version": 1, "entityId": 1, "signerAddress": "0x7e5f4552091a69125d5dfcb7b8c2659029395bdf", "permissions": [ { "type": "contract-access", "address": "0x2222222222222222222222222222222222222222" }, { "type": "native-token-transfer", "allowance": "1000000000000000" } ], "allowSignatures": false, "validAfter": 1791709200, "validUntil": 1794387600 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ] ```
## Parameters [#parameters] The optional `options` object defaults to `{}`. ### walletId [#walletid] - **Type:** `string` - **Optional** Filters keys to one account UUID. Omit options or pass `{}` to list all keys available to your credential across accounts. This does not broaden its grants. ```ts title="index.ts" import { namera } from "./client"; const sessions = await namera.sessionKeys.list({ walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] }); if (!sessions.success) throw new Error(sessions.error.message); console.log(sessions.data); ``` ## Errors [#errors] A filtered request can return `WALLET_NOT_FOUND`. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for authentication, transport, and contract errors. # 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. ```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); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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.
```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" } ```
Passkey approval uses this shape:
```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" } ```
## 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. # sessionKeys.revoke > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/session-keys/revoke-session-key Revoke a session’s Namera access and grants. `namera.sessionKeys.revoke()` revoke a session’s Namera access and grants. ## 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. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.revoke("0199dfe1-0000-7000-8000-000000001000"); if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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 the complete session. Never-installed sessions may become `revoked` immediately; installed or signed authority remains `revoking` until removal/reconciliation finishes. This fixture has an installed network, so server access is revoked while onchain removal is still required.
```json { "id": "0199dfe1-0000-7000-8000-000000001000", "organizationId": "0199dfe1-0000-7000-8000-000000001001", "walletId": "0199dfe1-0000-7000-8000-000000001002", "signingKeyId": "0199dfe1-0000-7000-8000-000000001003", "namespace": "eip155", "metadata": { "version": 1, "name": "Local agent" }, "policies": [], "policyHash": "9Z4ZzPfiQ4hIUpSXTY_nQ2E9-kjd2w_5wbLwIj7visI", "status": "revoking", "revokedAt": "2026-10-15T02:57:34.211Z", "createdAt": "2026-10-15T02:57:32.375Z", "signer": { "custody": "local", "algorithm": "secp256k1", "publicKey": "0x04c70cd5e6b1350f36bb3f47e4c50f276178a843ddc457189b962b660b81945ccee5bd6e75bbf22348c1ece286baeec6776e5cc66206f2b5de96cf0c8a0ca407e1" }, "wallet": { "id": "0199dfe1-0000-7000-8000-000000001002", "organizationId": "0199dfe1-0000-7000-8000-000000001001", "metadata": { "version": 1, "name": "Managed owner" }, "status": "active", "namespace": "eip155", "address": "0x3333333333333333333333333333333333333333", "owner": { "signingKeyId": "0199dfe1-0000-7000-8000-000000001004", "custody": "namera-managed", "provider": "1claw", "algorithm": "secp256k1" }, "createdAt": "2026-10-15T02:57:32.345Z", "updatedAt": "2026-10-15T02:57:32.345Z", "implementation": "alchemy-modular-v2", "data": { "version": 1, "modularAccountVersion": "2.0.0", "validatorType": "ecdsa_secp256k1", "entryPointVersion": "0.7", "accountMode": "factory", "factoryVersion": "2.0.0", "implementationVersion": "v1.0.0", "ownerAddress": "0x90C59223ac50061f5204826078944ec41bc56e0d", "salt": "0" } }, "creator": { "organizationMember": { "id": "0199dfe1-0000-7000-8000-000000001005", "userId": "0199dfe1-0000-7000-8000-000000001006", "organizationId": "0199dfe1-0000-7000-8000-000000001001", "organizationRoleId": "0199dfe1-0000-7000-8000-000000001007", "joinedAt": "2026-10-15T02:57:32.244Z" }, "user": { "id": "0199dfe1-0000-7000-8000-000000001006", "email": "0199dfe1-0000-7000-8000-000000001008@example.com", "emailVerified": true, "metadata": { "version": 1 }, "lastLoginAt": "2026-10-15T02:57:32.211Z" }, "organizationRole": { "id": "0199dfe1-0000-7000-8000-000000001007", "key": "owner", "permissions": [ "organization:read", "organization:update", "member:read", "member:update", "member:remove", "invitation:read", "invitation:create", "invitation:cancel", "role:read", "role:create", "role:update", "role:delete", "billing:read", "billing:update", "billing:cancel", "wallet:read", "wallet:create", "wallet:update", "session-key:read", "session-key:create", "session-key:revoke", "api-key:read", "api-key:create", "api-key:revoke", "execution:read", "mcp-authorization:read", "mcp-authorization:create", "mcp-authorization:revoke", "cli-authorization:read", "cli-authorization:create", "cli-authorization:revoke" ], "metadata": { "version": 1, "name": "Owner", "description": "Organization owner with full access" }, "type": "system", "systemRoleId": "0199dfe1-0000-7000-8000-000000001009" } }, "installations": [ { "id": "0199dfe1-0000-7000-8000-000000001010", "chainId": "eip155:11155111", "status": "installed", "authorization": { "version": 1, "entityId": 94541820, "signerAddress": "0xAB592704Fde287292b3a886Db80C0B6e7AC6DAdc", "permissions": [ { "type": "root" } ], "allowSignatures": false, "validAfter": 1792033052, "validUntil": 1792036652 }, "installTransactionHash": "0x2222222222222222222222222222222222222222222222222222222222222222", "uninstallTransactionHash": null } ] } ```
## Parameters [#parameters] ### sessionKeyId [#sessionkeyid] Type: `string`. Required. Resource UUID returned by creation, preparation, or recovery; not an address or transaction hash. ```ts title="index.ts" import { namera } from "./client"; const result = await namera.sessionKeys.revoke("0199dfe1-0000-7000-8000-000000001000"); // [!code focus] if (!result.success) throw new Error(result.error.message); console.log(result.data); ``` ## Behavior and errors [#behavior-and-errors] Requires `session-key:revoke` and can target any session in this workspace. Revocation atomically revokes grants and cancels unsigned installation requests. It does not erase onchain authority. Use `prepareOperation({ kind: "uninstall", ... })` and explicit approval for each installed network, then track confirmation. Signed operations must still reconcile. # Sign > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/signatures/sign Sign a UTF-8 message or EIP-712 typed data. `namera.sign(request)` prepares, validates, and completes a signature using the selected session key. It does not send a transaction. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`namespace`** (`"eip155"`): Chain namespace. - **`walletId`** (`string`): Account UUID. - **`chainId`** (`SupportedEvmChainId`): Signing network. - **`account`** (`` `0x${string}` ``): Smart-account address. - **`signature`** (`` `0x${string}` ``): Smart-account signature, not a bare EOA signature. - **`type`** (`"message" | "typed-data"`): Payload kind. ### Example Response [#example-response]
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "signature": "0x0000000100111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111b", "type": "message" } ```
## Parameters [#parameters] Pass a `SignRequest` object. The selected session needs installed signature authority and an API policy permitting the payload. ### namespace [#namespace] - **Type:** `"eip155"` - **Required** The blockchain namespace. Use `"eip155"` for every currently supported Namera network. This is not a chain ID; select the specific network with `chainId`. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", // [!code focus] walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ``` ### walletId [#walletid] - **Type:** `string` - **Required** The account UUID returned by `wallets.list()` or `wallets.get()`. Pass its `id`, not its onchain `address`. The account must be accessible to the client’s credential. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ``` ### sessionKeyId [#sessionkeyid] - **Type:** `string` - **Required** The session-key UUID returned by `sessionKeys.list()` or `sessionKeys.get()`. This identifies the delegated session, not its signing key or network installation. Execution and signing require an active grant for this key. Management reads may instead use explicit workspace `session-key:read` permission. For execution or signing, choose a key belonging to `walletId` with a confirmed installation on `chainId` and permissions that allow the requested operation. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", // [!code focus] chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ``` ### chainId [#chainid] - **Type:** `SupportedEvmChainId` - **Required** The target network in CAIP-2 format. For Base Sepolia, use `"eip155:84532"`, not `84532` or `"84532"`. Use the network on which the account will execute, sign, or verify the payload. The SDK restricts this field to the [supported network IDs](https://namera.ai/docs/sdk/supported-networks). Network availability is also checked by the API. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", // [!code focus] type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); console.log(signed.data); ``` ### type [#type] - **Type:** `"message" | "typed-data"` - **Required** Selects the payload format. Use `message` with `"message"` or `typedData` with `"typed-data"`. Do not supply both payload fields. ### message [#message] - **Type:** `string` - **Required when:** `type` is `"message"` The exact UTF-8 text to sign or verify. Whitespace and capitalization are part of the payload. A string such as `"0x1234"` is text, not raw bytes. ### typedData [#typeddata] - **Type:** `EvmTypedData` - **Required when:** `type` is `"typed-data"` An EIP-712 payload containing `domain`, `types`, `primaryType`, and `message`. Use the identical payload when verifying its signature. ```ts title="index.ts" import type { EvmTypedData } from "@namera-ai/sdk"; const typedData = { domain: { // [!code focus:6] name: "Namera Example", version: "1", chainId: 84532, verifyingContract: "0x3333333333333333333333333333333333333333", }, types: { Greeting: [{ name: "contents", type: "string" }] }, primaryType: "Greeting", message: { contents: "Hello from Namera" }, } satisfies EvmTypedData; ``` #### typedData.domain [#typeddatadomain] - **Type:** `EvmTypedData["domain"]` - **Required** The signing domain. Its fields are optional: `name` and `version` are strings; `chainId` is a nonnegative integer; `verifyingContract` is a 20-byte address; `salt` is a 32-byte hex value. Unlike the request’s CAIP-2 `chainId`, this domain uses a number such as `84532`. Use the domain expected by the verifying application. #### typedData.types [#typeddatatypes] - **Type:** `Record` - **Required** Definitions of the structs used by the payload. Struct names, field names, and field types must be nonempty strings. Each struct needs at least one field. #### typedData.primaryType [#typeddataprimarytype] - **Type:** `string` - **Required** The root struct name from `types`, such as `"Greeting"`. It determines how the message fields are encoded. #### typedData.message [#typeddatamessage] - **Type:** `Record` - **Required** Values matching the root struct. Use JSON-compatible values. Represent large integers as decimal strings, not JavaScript `bigint`, to preserve precision. #### Sign typed data [#sign-typed-data] Use `type: "typed-data"` with the complete payload. The session’s signature policy must permit its domain and primary type. Replace the domain’s contract address with the one expected by your application. ```ts title="index.ts" import type { EvmTypedData } from "@namera-ai/sdk"; import { namera } from "./client"; const typedData = { domain: { name: "Namera Example", version: "1", chainId: 84532, verifyingContract: "0x3333333333333333333333333333333333333333", }, types: { Greeting: [{ name: "contents", type: "string" }], }, primaryType: "Greeting", message: { contents: "Hello from Namera" }, } satisfies EvmTypedData; ``` ## Errors [#errors] Signature policy, authorization, billing, and signing failures return `success: false`. Prepared-payload or signature validation failures use `kind: "signer"`. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for shared authentication, transport, and contract errors. Guides: [Sign Messages](https://namera.ai/docs/sdk/guides/signing/sign-messages) and [Sign Typed Data](https://namera.ai/docs/sdk/guides/signing/sign-typed-data). # Verify Signature > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/reference/signatures/verify-signature Verify a smart-account signature against its original payload. `namera.verifySignature(request)` performs read-only verification. It requires access to the account, but no session-key ID. ## Usage [#usage] Install `@namera-ai/sdk` and set `NAMERA_API_KEY`. Replace example IDs with resources available to your credential. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "message", message, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ``` ```ts title="client.ts" import { NameraClient } from "@namera-ai/sdk"; export const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); ``` ## Returns [#returns] API methods return a `Promise>`. 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. - **`namespace`** (`"eip155"`): Chain namespace. - **`walletId`** (`string`): Account UUID. - **`chainId`** (`SupportedEvmChainId`): Verification network. - **`account`** (`` `0x${string}` ``): Smart-account address. - **`valid`** (`boolean`): Whether the account accepts this signature for the payload. - **`type`** (`"message" | "typed-data"`): Payload kind. ### Example Response [#example-response]
```json { "namespace": "eip155", "walletId": "0199dfe1-0000-7000-8000-000000000001", "chainId": "eip155:84532", "account": "0x1111111111111111111111111111111111111111", "valid": true, "type": "message" } ```
## Parameters [#parameters] Pass a `VerifySignatureRequest` object. No session-key ID is needed. For `type: "typed-data"`, provide `typedData` instead of `message`. ### namespace [#namespace] - **Type:** `"eip155"` - **Required** The blockchain namespace. Use `"eip155"` for every currently supported Namera network. This is not a chain ID; select the specific network with `chainId`. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", // [!code focus] walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "message", message, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ``` ### walletId [#walletid] - **Type:** `string` - **Required** The account UUID returned by `wallets.list()` or `wallets.get()`. Pass its `id`, not its onchain `address`. The account must be accessible to the client’s credential. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", // [!code focus] sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "message", message, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ``` ### chainId [#chainid] - **Type:** `SupportedEvmChainId` - **Required** The target network in CAIP-2 format. For Base Sepolia, use `"eip155:84532"`, not `84532` or `"84532"`. Use the network on which the account will execute, sign, or verify the payload. The SDK restricts this field to the [supported network IDs](https://namera.ai/docs/sdk/supported-networks). Network availability is also checked by the API. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", // [!code focus] type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "message", message, signature: signed.data.signature, }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ``` ### type [#type] - **Type:** `"message" | "typed-data"` - **Required** Selects the payload format. Use `message` with `"message"` or `typedData` with `"typed-data"`. Do not supply both payload fields. ### message [#message] - **Type:** `string` - **Required when:** `type` is `"message"` The exact UTF-8 text to sign or verify. Whitespace and capitalization are part of the payload. A string such as `"0x1234"` is text, not raw bytes. ### typedData [#typeddata] - **Type:** `EvmTypedData` - **Required when:** `type` is `"typed-data"` An EIP-712 payload containing `domain`, `types`, `primaryType`, and `message`. Use the identical payload when verifying its signature. ```ts title="index.ts" import type { EvmTypedData } from "@namera-ai/sdk"; const typedData = { domain: { // [!code focus:6] name: "Namera Example", version: "1", chainId: 84532, verifyingContract: "0x3333333333333333333333333333333333333333", }, types: { Greeting: [{ name: "contents", type: "string" }] }, primaryType: "Greeting", message: { contents: "Hello from Namera" }, } satisfies EvmTypedData; ``` #### typedData.domain [#typeddatadomain] - **Type:** `EvmTypedData["domain"]` - **Required** The signing domain. Its fields are optional: `name` and `version` are strings; `chainId` is a nonnegative integer; `verifyingContract` is a 20-byte address; `salt` is a 32-byte hex value. Unlike the request’s CAIP-2 `chainId`, this domain uses a number such as `84532`. Use the domain expected by the verifying application. #### typedData.types [#typeddatatypes] - **Type:** `Record` - **Required** Definitions of the structs used by the payload. Struct names, field names, and field types must be nonempty strings. Each struct needs at least one field. #### typedData.primaryType [#typeddataprimarytype] - **Type:** `string` - **Required** The root struct name from `types`, such as `"Greeting"`. It determines how the message fields are encoded. #### typedData.message [#typeddatamessage] - **Type:** `Record` - **Required** Values matching the root struct. Use JSON-compatible values. Represent large integers as decimal strings, not JavaScript `bigint`, to preserve precision. ### signature [#signature] - **Type:** `` `0x${string}` `` - **Required** The complete signature returned by `sign()`, including its validation envelope. Do not strip it to a bare EOA signature. Supply the original payload, account, and network. A successful request can return `valid: false`; only `data.valid: true` means the signature was accepted. ```ts title="index.ts" import { namera } from "./client"; const message = "Hello from Namera"; const signed = await namera.sign({ namespace: "eip155", walletId: "0199dfe1-0000-7000-8000-000000000001", sessionKeyId: "0199dfe1-0000-7000-8000-000000000002", chainId: "eip155:84532", type: "message", message, }); if (!signed.success) throw new Error(signed.error.message); const verification = await namera.verifySignature({ namespace: "eip155", walletId: signed.data.walletId, chainId: signed.data.chainId, type: "message", message, signature: signed.data.signature, // [!code focus] }); if (!verification.success) throw new Error(verification.error.message); console.log(verification.data); ``` ## Errors [#errors] `VERIFICATION_FAILED` indicates verification could not be completed; `valid: false` is a completed check that rejected the signature. See [Handling Results and Errors](https://namera.ai/docs/sdk/handling-results-and-errors) for shared authentication, transport, and contract errors. Guide: [Verify Signatures](https://namera.ai/docs/sdk/guides/signing/verify-signatures). # Supported Networks > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/sdk/supported-networks Choose a mainnet or testnet for your SDK calls. Namera supports eight EVM networks. Use `namespace: "eip155"` and the full `chainId` string when executing, simulating, or signing. ## Mainnets [#mainnets] | Network | Chain ID | | ------------ | -------------- | | Ethereum | `eip155:1` | | Base | `eip155:8453` | | Arbitrum One | `eip155:42161` | | OP Mainnet | `eip155:10` | ## Testnets [#testnets] | Network | Chain ID | | ---------------- | ----------------- | | Ethereum Sepolia | `eip155:11155111` | | Base Sepolia | `eip155:84532` | | Arbitrum Sepolia | `eip155:421614` | | OP Sepolia | `eip155:11155420` | The [Getting Started](https://namera.ai/docs/sdk/getting-started) walkthrough uses **Base Sepolia**. Fund the account with test ETH on that network before sending a transfer. ## Select a Network [#select-a-network] Import `SupportedEvmChainId` from the SDK to type a network in your configuration: ```ts title="index.ts" import { NameraClient, type SupportedEvmChainId } from "@namera-ai/sdk"; const namera = new NameraClient({ apiKey: process.env.NAMERA_API_KEY!, }); const chainId: SupportedEvmChainId = "eip155:84532"; const result = await namera.sessionKeys.get("0199dfe1-0000-7000-8000-000000000002"); if (!result.success) throw new Error(result.error.message); const installation = result.data.installations.find( (entry) => entry.chainId === chainId && entry.status === "installed", ); if (!installation) throw new Error("Install this session key on Base Sepolia first."); ``` Replace the example session-key ID with your own. An installation on one network does not authorize another. Its validity period and permissions must also allow your operation. Changing `chainId` selects a network; it does not move funds between networks. Use the recipient or contract address for the network you selected. If a request returns `NETWORK_PAUSED`, wait for that network to be re-enabled before submitting a new operation. You can still check existing submissions. Next, learn how to [handle results and errors](https://namera.ai/docs/sdk/handling-results-and-errors). # Why Namera > Documentation index: [llms.txt](https://namera.ai/llms.txt). Source: https://namera.ai/docs/why-namera A brief primer on why we built Namera Giving an agent the ability to act onchain sounds simple until you try to put boundaries around it. The moment it can move funds, sign messages, or interact with contracts, you need to decide what it should be allowed to do and what should remain outside its control. Namera is built around that question: how do you give an agent useful access to a wallet without giving it the authority of the wallet owner? ## The Problem with Agent Wallets [#the-problem-with-agent-wallets] Passing a wallet's private key through a `.env` file gets you to a working integration quickly. But the key does not know which task the agent is carrying out. If it controls the account, it can authorize whatever the account allows, not just the operation you intended. You can add checks to your application, but those checks are separate from the authority of the key itself. A spending rule in a prompt is not a spending limit on a wallet. Giving several agents the same owner key also makes it harder to separate their access or withdraw permission from just one of them. Moving the key behind an API changes where it is held. It does not, on its own, define what each caller should be allowed to do. Key custody and delegated permissions are different problems. Both need an explicit answer. ## What Namera Does Differently [#what-namera-does-differently] Namera does not ask an agent to act as the account owner. It gives you a way to issue scoped session keys and grant each integration access to the keys it needs. Depending on the permissions you configure, you can restrict: - which networks the session key can use - which contracts and functions it can call - which tokens it can transfer and how much it can spend - how much native value and gas it can use - when execution access starts and expires - whether it can sign messages or typed data The current EVM accounts use Alchemy Modular Account V2. Session permissions are installed on the smart account with owner approval on each network. Additional API policies narrow signature requests authorized through Namera. These are separate layers: an API restriction is not automatically an onchain restriction. The same distinction matters when withdrawing access. Revoking a session key blocks its use through Namera. Removing its onchain permissions requires a separate owner-approved operation on each network where it was installed. Onchain signature authority is explicitly enabled and is not removed simply because execution access expires. Permissions limit authority, not judgment. An allowed transaction can still be a bad decision. The goal is to define the access a task needs and avoid granting more than that. ## Choose How You Hold Keys [#choose-how-you-hold-keys] Account ownership and session-key custody are independent choices. A user-owned passkey account or a 1Claw-managed account can use local or managed session keys. With a local session key, your client holds the private key and signs locally. With a managed session key, Namera requests signatures through 1Claw. Neither choice turns the session key into an account owner; its installed permissions and Namera authorization still determine what it can do. ## Designed to Work with Your Tools [#designed-to-work-with-your-tools] You should not need a different permission model every time you change how an agent connects. The [SDK](https://namera.ai/docs/sdk), [CLI](https://namera.ai/docs/cli), and [MCP](https://namera.ai/docs/mcp) clients use the same grant-scoped execution and signing capabilities. Use the SDK from a TypeScript application, the CLI from your terminal, or MCP from a compatible agent client. The interface changes. The account, session key, and permissions behind it stay the same.