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

# Link Wallets and Access Agreements

> Prove wallet control, link wallets to your Shodai account, and understand how linked wallets affect agreement visibility.

For the complete documentation index, see
[llms.txt](https://docs.shodai.network/llms.txt).

Link each wallet you control to your Shodai account once. External API requests authenticated as that account can then discover agreements that name any linked address, whether the agreement already exists or is created later.

Assigning an address to an agreement does not require the wallet to be linked first. It also does not create an invitation or acceptance step.

## Keep identity, visibility, and authority separate

| Concept                | What it means                                                                                                     | What it does not mean                                                       |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| Linked-wallet identity | A signature proves that your Shodai account controls a wallet address.                                            | Shodai does not take custody of the wallet or gain signing access.          |
| Agreement visibility   | Agreements can be listed when a participant address matches any wallet linked to the authenticated account.       | Visibility alone does not authorize agreement inputs.                       |
| Input authority        | The authored input `issuer` identifies eligible signing wallets, and the submission must carry a valid signature. | Linking a wallet does not grant blanket permission to operate an agreement. |

## Link a wallet in the Developer Portal

<Steps>
  <Step title="Sign in to the Developer Portal">
    Sign in to the Shodai account that should gain wallet-based agreement
    visibility.
  </Step>

  <Step title="Open your wallets">
    Under **Visibility**, select **Connected wallets**.
  </Step>

  <Step title="Prove wallet control">
    Choose **Connect wallet**, select the browser wallet, and sign the challenge.
    The signature proves control without transferring custody.
  </Step>

  <Step title="Confirm the linked address">
    Confirm that the wallet address appears on your account. Credentials for
    that Shodai account can now use the linked address as an
    agreement-visibility signal.
  </Step>
</Steps>

## Link a wallet through the External API

Use an authenticated Shodai account credential with `agreements.write` and a wallet client for the address you are linking. The example uses an OAuth bearer access token. `X-API-Key` is the alternative credential header.

<Steps>
  <Step title="Request a wallet challenge">
    Send the wallet address to `POST /v0/siwe/nonce`. The response supplies the
    nonce and issued-at value for the EIP-4361 message.
  </Step>

  <Step title="Build and sign the EIP-4361 message">
    Keep the domain, URI, address, nonce, chain ID, and issued-at value
    consistent. Sign the exact message that you submit for verification.
  </Step>

  <Step title="Verify and link the wallet">
    Submit the address, exact message, signature, domain, and chain ID to `POST
            /v0/siwe/verify`. A successful response links the verified address to the
    authenticated Shodai account.
  </Step>
</Steps>

```typescript theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { createWalletClient, http, type Hex } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { lineaSepolia } from 'viem/chains';
import { createSiweMessage } from 'viem/siwe';

const baseUrl = process.env.SHODAI_API_BASE_URL!.replace(/\/+$/, '');
const apiUrl = new URL(baseUrl);
const accessToken = process.env.SHODAI_ACCESS_TOKEN!;
const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as Hex);
const walletClient = createWalletClient({
  account,
  chain: lineaSepolia,
  transport: http(process.env.RPC_URL),
});
const chainId = lineaSepolia.id;
const address = account.address;
const headers = {
  Authorization: `Bearer ${accessToken}`,
  'Content-Type': 'application/json',
};

const nonceResponse = await fetch(`${baseUrl}/v0/siwe/nonce`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ address }),
});
if (!nonceResponse.ok) {
  throw new Error(
    `Nonce request failed: ${nonceResponse.status} ${await nonceResponse.text()}`,
  );
}
const { data: challenge } = await nonceResponse.json();

const message = createSiweMessage({
  domain: apiUrl.host,
  address,
  statement: 'Prove control of this wallet to Shodai.',
  uri: apiUrl.origin,
  version: '1',
  chainId,
  nonce: challenge.nonce,
  issuedAt: new Date(challenge.issuedAt),
});
const signature = await walletClient.signMessage({ account, message });

const verificationResponse = await fetch(`${baseUrl}/v0/siwe/verify`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    address,
    message,
    signature,
    domain: apiUrl.host,
    chainId,
  }),
});
if (!verificationResponse.ok) {
  throw new Error(
    `Wallet verification failed: ${verificationResponse.status} ${await verificationResponse.text()}`,
  );
}
const { data: verifiedWallet } = await verificationResponse.json();
console.log(verifiedWallet);

// Use a credential with agreements.read for the same Shodai account.
const agreementsResponse = await fetch(`${baseUrl}/v0/agreements`, {
  headers: {
    Authorization: `Bearer ${process.env.SHODAI_READ_ACCESS_TOKEN!}`,
  },
});
if (!agreementsResponse.ok) {
  throw new Error(
    `Agreement list failed: ${agreementsResponse.status} ${await agreementsResponse.text()}`,
  );
}
const { data: agreements } = await agreementsResponse.json();
console.log(agreements);
```

See [Create wallet challenge](/reference/api/wallet-access/create-wallet-verification-challenge) and [Verify and link wallet](/reference/api/wallet-access/verify-and-link-wallet) for request and response details.

## What becomes visible

List agreements with an `agreements.read` credential for the same Shodai account. Agreements that already name the linked address can appear after linking, and future agreements that name it require no separate acceptance step.

Linking and unlinking affect only visibility derived from the account-wallet association. Creator, owner, contributor, or observer access can keep an agreement visible through another documented access signal.

## Interpret `walletBinding` as provenance

The SIWE verification response uses `verified_via_siwe` to report how the account wallet was verified. An agreement participant's `walletBinding` separately reports how that address was established on the agreement record.

| Participant value   | Provenance                                                           |
| ------------------- | -------------------------------------------------------------------- |
| `partner_asserted`  | An API caller supplied the participant address directly.             |
| `verified_via_auth` | Shodai resolved the address through participant identity.            |
| `verified_via_siwe` | SIWE proof established the participant binding when it was recorded. |

These values are not current access decisions or input-permission flags. Linking an address later does not rewrite an existing `partner_asserted` participant record.

## Understand the authority boundary

Linking proves wallet control. It does not transfer custody, and Shodai cannot sign agreement inputs for you. A wallet may submit an input only when the authored input [`issuer`](/workflow/author-agreement-json#author-states-inputs-issuers-and-transitions-as-workflow) allows it and the submission includes a valid signature from that wallet.

## Unlink a self-linked wallet

You can remove a self-linked SIWE wallet from **Visibility > Connected wallets** in the Developer Portal. Unlinking removes visibility derived solely from that account-wallet association; relinking restores the identity signal. Dynamic or operator-managed wallets follow different removal rules and are not necessarily self-unlinkable.

Continue with [Deploy an Agreement](/workflow/deploy-an-agreement) to assign participant addresses or [Operate a Deployed Agreement](/workflow/operate-a-deployed-agreement) to submit an authorized input.
