---
title: "Register a signer key"
method: POST
path: "/v1/auth/register-signer"
tags: ["Authentication"]
---

# Register a signer key

`POST /v1/auth/register-signer`

## Request

- Base URL: `https://api.testnet.rise.trade`
- URL: `https://api.testnet.rise.trade/v1/auth/register-signer`
- Auth: none required
- TypeScript: <https://skmtc.dev/rise/apis/risex-rest-api/docs/v1/auth/register-signer/post.ts> (a function with typed inputs; its response is checked against the schema)

Register a signer (session) key for an account. The account authorises the signer and the signer proves consent, so this requires **two EIP-712 signatures**.

**Prerequisites:**
1. `GET /v1/auth/eip712-domain` — EIP-712 domain (`name`, `version`, `chainId`, `verifyingContract` = Authorization contract). Both signatures use this same domain.
2. `GET /v1/nonce-state/{account}` — `nonce_anchor` and `current_bitmap_index`. Send them back as `nonce_anchor` / `nonce_bitmap_index` and sign the exact same values.

**1. Account signs `RegisterSigner`:**
```
RegisterSigner(address account,address signer,string message,uint32 expiration,uint48 nonceAnchor,uint8 nonceBitmap)
```
Struct hash: `keccak256(abi.encode(TYPEHASH, account, signer, keccak256(bytes(message)), expiration, nonceAnchor, nonceBitmap))`

**2. Signer signs `VerifySigner`:**
```
VerifySigner(address account,uint48 nonceAnchor,uint8 nonceBitmap)
```
Struct hash: `keccak256(abi.encode(TYPEHASH, account, nonceAnchor, nonceBitmap))`

**Signature encoding:** `account_signature` and `signer_signature` are **0x-prefixed hex** strings. This differs from `permit.signature` on the trading endpoints, which is a protobuf `bytes` field and is therefore **base64** in JSON.

**Idempotent:** if the signer is already active, the call is a no-op and returns `success: true` with an empty `transaction_hash`.

**Failure modes:** a wrong struct or field order fails signature recovery. A `nonceAnchor` other than the current anchor or the current anchor + 1 reverts with `InvalidNonceAnchor`, which looks like a nonce bug but is usually a mismatch between the signed and submitted values.

## Request body

- ApiRegisterSignerRequest
  - `account` string: Account address in hex format (0x...)
  - `signer` string: Signer address in hex format (0x...)
  - `message` string: Arbitrary message to be included in the signature
  - `nonce_anchor` string: Bitmap nonce anchor (uint48) from GetNonceState
  - `expiration` string, uint64: Unix timestamp when the signer registration expires
  - `account_signature` string: EIP712 signature from account (65 bytes hex)
  - `signer_signature` string: EIP712 signature from signer (65 bytes hex)
  - `nonce_bitmap_index` integer: Bitmap index within the nonce anchor epoch (0-207)
  - `label` string: Optional label to identify this signer key

## Response `200`

A successful response.

- ApiRegisterSignerResponse
  - `transaction_hash` string: Transaction hash of the signer registration
  - `success` boolean: Whether the signer registration succeeded
  - `status` integer: Status after registration: 0=NotExist, 1=Active, 2=Revoked
  - `block_number` string, uint64: Block number where the registration was confirmed

## Other responses

- `default`: An unexpected error response.

## Changes

- **2026-11-03** `98eabcd6a6ad`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/rise/apis/risex-rest-api/changes/v1/auth/register-signer/post.md)

---

[API](https://skmtc.dev/rise/apis/risex-rest-api.md) - [All operations](https://skmtc.dev/rise/apis/risex-rest-api/llms.txt) - [OpenAPI document](https://skmtc.dev/rise/apis/risex-rest-api/revisions/98eabcd6a6ad?raw)
