---
title: "Create a multisig wallet"
method: POST
path: "/v1/multisig-wallets"
tags: ["Multisig Wallets"]
---

# Create a multisig wallet

`POST /v1/multisig-wallets`

## Request

- Base URL: `https://api.prod.keyban.io`
- URL: `https://api.prod.keyban.io/v1/multisig-wallets`
- Auth: one of:
  - API key in header `X-Api-Key`
  - `bearer` (a scheme the document does not define)

Create the organization multisig wallet for a network, with the number of signatures a transfer will require (M of N). Nothing is deployed on-chain yet: the account is created once M signers have bound a key from the signer app and been validated — its address and threshold are fixed at that point. Available from the Agent Wallet Growth plan, or on a grant by Keyban.

## Request body

- CreateMultisigWalletDto
  - `label` string, required: Admin-chosen display name shown in the treasury UI (not unique, never used for lookups)
  - `network` 'EthereumAnvil' | 'BaseSepolia' | 'BaseMainnet' | 'XdcApothem' | 'XdcMainnet', required: EVM network the wallet lives on. One multisig wallet per organization × network.
  - `threshold` integer, required: Signatures required to move funds (M of N). The account deploys once M signers are validated, and the value is fixed at initialization. Capped at 10 to keep the enrollment ceremony workable.
  - `invitedEmails` string[]: Organization members invited to enrol a signing key on the freshly created treasury, one email per person. Each must already be an `admin` or `owner` of the organization — enrolment is the invitee’s own authenticated call, so an outsider could never complete it. Duplicates are ignored. Inviting is best-effort: a mail failure never undoes the treasury.

## Response `201`

Multisig wallet created, awaiting its signers. The creator is invited to enrol on it as part of the same transaction (enrolment is invitation-only), without a mail to themselves. Any `invitedEmails` are processed after the wallet exists and never affect this status: a rejected address or a mail outage still returns the treasury.

- MultisigWalletDtoOutput
  - `id` string, uuid, required: Entity UUID
  - `createdAt` string, date-time, required: Creation date (ISO 8601)
  - `updatedAt` string, date-time, required: Last update date (ISO 8601)
  - `label` string, required: Human-readable label for the wallet
  - `address` string, required: On-chain address of the wallet. Empty until its signers hold keys and the deployment lands.
  - `status` 'awaiting_signer' | 'deploying' | 'active' | 'failed', required: Current deployment status of the wallet.
  - `network` 'EthereumAnvil' | 'BaseSepolia' | 'BaseMainnet' | 'XdcApothem' | 'XdcMainnet', required: EVM network of the wallet.
  - `threshold` integer, required: Signatures required to authorize a transfer (M of N), as recorded at deployment. Not re-read from chain: an out-of-band operator change is not reflected here.
  - `mayEnroll` boolean, required: **Relative to whoever reads this response — not a property of the treasury.** The same treasury serves `true` to one admin and `false` to another, and the value changes for a given reader over time. True when the session user holds a live (unconsumed) invitation on this treasury and has no live signer enrolment on it, i.e. exactly when `POST /multisig-wallets/{id}/signers` would get past the invitation guard. Enrolment is reserved to invitees, so a client should only offer the ceremony when this is true. Always `false` for an API key: there is no session user to be invited, and an API key can never enrol.
  - `awaitingMySignature` boolean, required: **Relative to whoever reads this response — not a property of the treasury.** Two signers of the same treasury legitimately read different values, and the value flips for a given reader as transfers come and go. True when the session user is an `active` signer here — a key already in the on-chain signer set, the only one the account accepts a signature from — **and** a transfer of this treasury is still `pending` without their own signature on it: exactly the state where `POST /multisig-wallets/{id}/intents/{intentId}/approvals` is waiting for them. It goes back to `false` the moment they sign, even while the lot keeps collecting the remaining signatures. A signer app can badge the treasuries that need its owner without opening each transfer list. Always `false` for an API key: there is no session user to owe a signature, and a key can never sign.

## Other responses

- `403`: Session-authenticated user required (`MULTISIG_WALLET_SESSION_REQUIRED`), the plan does not include the treasury (Agent Wallet Growth and above) and Keyban granted none (`QUOTA_FEATURE_RESTRICTED`), or the network is not allowed for the organization (`QUOTA_NETWORK_RESTRICTED`)
- `409`: The organization already has a multisig wallet on this network — including a `failed` one, which keeps the slot until deleted

---

[API](https://skmtc.dev/keyban/apis/keyban-rest-apis.md) · [All operations](https://skmtc.dev/keyban/apis/keyban-rest-apis/llms.txt) · [OpenAPI document](https://skmtc.dev/keyban/apis/keyban-rest-apis/revisions/0bb79a1da961?raw)
