> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Signers

> Grant and revoke the ability to sign with a business-account wallet from Kotlin.

<Note>
  Business Accounts are in **early access**. See the [overview](/docs/kotlin/business-accounts/overview) for the model.
</Note>

A **signer** can approve transactions and messages with a specific wallet. Signing access is separate from [membership roles](/docs/kotlin/business-accounts/members-and-roles). Adding a signer grants them access, and removing one revokes only theirs, so the wallet and other signers stay intact.

<Info>
  Only an owner or admin can add signers, and the caller must already be an active signer on that wallet.
</Info>

## Add a signer

`addSigner` grants signing access to a user, and returns an `AddBusinessAccountSignerResponse` with the new `shareSetId`. Identify the target with a `TargetIdentity`: a known `userId`, or an `identifier` plus `identifierType` (for example an email, in which case the user is created if they do not exist yet).

```kotlin theme={"system"}
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.BusinessAccountSignerIdentifierType
import com.dynamic.sdk.android.Models.BusinessAccountSignerType
import com.dynamic.sdk.android.Models.TargetIdentity

val sdk = DynamicSDK.getInstance()

val wallet = sdk.wallets.userWallets.firstOrNull() ?: return
val walletId = wallet.id ?: return
// Load both values from your secure storage.
val password = loadCurrentSignerPassword()
val targetSignerPassword = loadTargetSignerPassword()

val response = sdk.businessAccounts.addSigner(
    accountAddress = wallet.address,
    chainName = wallet.chain,
    targetSignerIdentity = TargetIdentity(
        identifier = "teammate@acme.com",
        identifierType = BusinessAccountSignerIdentifierType.email
    ),
    businessAccountId = account.id,
    walletId = walletId,
    signerType = BusinessAccountSignerType.endUser,
    password = password,
    targetSignerPassword = targetSignerPassword
)

println(response.shareSetId)
```

<ParamField path="accountAddress" type="String" required>
  Address of the wallet the caller signs with, from `wallet.address`.
</ParamField>

<ParamField path="chainName" type="String" required>
  Chain of that wallet, from `wallet.chain` (for example `EVM` or `SOL`).
</ParamField>

<ParamField path="targetSignerIdentity" type="TargetIdentity" required>
  Who to add. Set `userId` for a known user, or `identifier` plus `identifierType`. For a phone number, also set `smsCountryCode`; for a social account, set `socialProvider`.
</ParamField>

<ParamField path="businessAccountId" type="String?">
  The account that owns the wallet.
</ParamField>

<ParamField path="walletId" type="String?">
  The wallet to add the signer to.
</ParamField>

<ParamField path="signerType" type="BusinessAccountSignerType?">
  `endUser` for a person, `server` for a server signer.
</ParamField>

<ParamField path="password" type="String?">
  Your password, when your key share is password-encrypted and you have not already unlocked it this session. It unlocks your own key share, and is never applied to the new signer's share.
</ParamField>

<ParamField path="targetSignerPassword" type="String?">
  A separate developer-managed value that encrypts the new signer's key share before backup. It is required when wallet passwords are required by your environment, and optional otherwise.
</ParamField>

`identifierType` is a `BusinessAccountSignerIdentifierType`: `email`, `phoneNumber`, `externalUserId`, `socialUsername`, `socialAccountId`, or `id`.

## Passwords when adding a signer

A password encrypts one person's key share, not the wallet. `password` and `targetSignerPassword` protect different shares.

1. `password` unlocks your own key share so the reshare can run. If the share is already unlocked for this session, you can omit it.
2. The reshare mints a new key share for the signer you add. Your own share set is untouched.
3. The SDK encrypts the new share locally with `targetSignerPassword`, then sends only the encrypted share to Dynamic for backup.
4. Your application makes `targetSignerPassword` available to the target signer after authentication. They use it to recover their share, then replace it with a user-controlled password by calling `setPassword`.

<Warning>
  If wallet passwords are required by your environment, omitting `targetSignerPassword` rejects the request before the reshare starts, with the error `A target signer password is required for this environment.` Otherwise, the field is optional and the SDK uses the environment's default encryption instead of a caller-controlled password.
</Warning>

Your application is responsible for generating, protecting, and retrieving `targetSignerPassword`. Derive it per signer, for example from a per-signer salt and a server-side secret held in your backend, and return it only over an authenticated request. Do not reuse the current signer's password. Dynamic's backup service does not receive the raw value. See [Password encryption](/docs/kotlin/wallets/embedded-wallets/mpc/password-encryption).

## Read the current signers

`get` returns the account with its signers, so you can show who can sign and get the `signerId` needed for removal.

```kotlin theme={"system"}
val detail = sdk.businessAccounts.get(businessAccountId = account.id)

detail.signers.filter { it.walletId == walletId }.forEach { signer ->
    println("${signer.id}, type: ${signer.type}, user: ${signer.userId ?: "none"}")
}
```

## Remove a signer

`removeSigner` revokes a signer's access to one wallet, and returns the removed `BusinessAccountSigner`.

```kotlin theme={"system"}
val removed = sdk.businessAccounts.removeSigner(
    businessAccountId = account.id,
    walletId = walletId,
    signerId = signerId
)
```

<Warning>
  You cannot remove the **last active signer** on a wallet, because nobody could then approve transactions. Add another signer, or [remove the wallet](/docs/kotlin/business-accounts/add-wallets), first.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Members and roles" icon="users" href="/docs/kotlin/business-accounts/members-and-roles">
    Administer who can manage the account.
  </Card>

  <Card title="Sign transactions" icon="signature" href="/docs/kotlin/business-accounts/signing">
    Use a signer's share to sign.
  </Card>
</CardGroup>
