# 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.

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

```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);
```

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

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

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

</Tab>
</Tabs>

## Returns [#returns]

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

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

- **`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]

<div className="docs-response">

```json
{
  "namespace": "eip155",
  "walletId": "0199dfe1-0000-7000-8000-000000000001",
  "chainId": "eip155:84532",
  "account": "0x1111111111111111111111111111111111111111",
  "valid": true,
  "type": "message"
}
```

</div>

## 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<string, readonly { name: string; type: string }[]>`
- **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<string, Json>`
- **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).
