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

# Configure sandbox

> Set up API permission groups, API keys, and the shared Anchorage Digital key for the wealth management integration.

export const KeyPairGenerator = () => {
  const [signingKey, setSigningKey] = useState("");
  const [publicKey, setPublicKey] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [copied, setCopied] = useState({});
  const bytesToHex = bytes => Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
  const generateKeys = async () => {
    setLoading(true);
    setError("");
    setSigningKey("");
    setPublicKey("");
    try {
      const keyPair = await crypto.subtle.generateKey({
        name: "Ed25519"
      }, true, ["sign", "verify"]);
      const [privateKeyBuffer, publicKeyBuffer] = await Promise.all([crypto.subtle.exportKey("pkcs8", keyPair.privateKey), crypto.subtle.exportKey("spki", keyPair.publicKey)]);
      const rawSeed = new Uint8Array(privateKeyBuffer).slice(16);
      const rawPublicKey = new Uint8Array(publicKeyBuffer).slice(12);
      setSigningKey(bytesToHex(rawSeed));
      setPublicKey(bytesToHex(rawPublicKey));
    } catch (err) {
      setError("Key generation failed. Your browser may not support Ed25519 (requires Chrome 113+, Firefox 130+, or Safari 17+).");
    } finally {
      setLoading(false);
    }
  };
  const copyToClipboard = async (text, id) => {
    try {
      await navigator.clipboard.writeText(text);
      setCopied(prev => ({
        ...prev,
        [id]: true
      }));
      setTimeout(() => setCopied(prev => ({
        ...prev,
        [id]: false
      })), 2000);
    } catch {}
  };
  const fieldStyle = {
    fontFamily: "monospace",
    fontSize: "12px",
    background: "var(--background-color, #f4f5f5)",
    border: "1px solid var(--border-color, #e5e7eb)",
    borderRadius: "6px",
    padding: "10px 12px",
    wordBreak: "break-all",
    color: "var(--text-color, #111)",
    minHeight: "40px"
  };
  const labelStyle = {
    fontSize: "12px",
    fontWeight: 600,
    marginBottom: "6px",
    color: "var(--muted-text-color, #6b7280)",
    textTransform: "uppercase",
    letterSpacing: "0.05em"
  };
  const copyBtnStyle = active => ({
    marginTop: "6px",
    padding: "4px 10px",
    fontSize: "12px",
    borderRadius: "5px",
    border: "1px solid var(--border-color, #e5e7eb)",
    background: active ? "#16a34a" : "transparent",
    color: active ? "#fff" : "var(--text-color, #374151)",
    cursor: "pointer",
    transition: "background 0.15s, color 0.15s"
  });
  const generateBtnStyle = {
    padding: "9px 18px",
    fontSize: "14px",
    fontWeight: 600,
    borderRadius: "7px",
    border: "none",
    background: loading ? "#93c5fd" : "#3b82f6",
    color: "#fff",
    cursor: loading ? "default" : "pointer",
    transition: "background 0.15s"
  };
  const wrapperStyle = {
    borderRadius: "10px",
    border: "1px solid var(--border-color, #e5e7eb)",
    padding: "20px 24px",
    maxWidth: "680px",
    display: "flex",
    flexDirection: "column",
    gap: "16px"
  };
  return <div style={wrapperStyle}>
      <div style={{
    display: "flex",
    flexDirection: "column",
    gap: "4px"
  }}>
        <div style={{
    fontWeight: 700,
    fontSize: "15px"
  }}>Ed25519 key pair generator</div>
        <div style={{
    fontSize: "13px",
    color: "var(--muted-text-color, #6b7280)"
  }}>
          Generate a signing key and public key for use with the Anchorage Digital API. Keys are generated locally in your browser — never transmitted.
        </div>
      </div>

      <button style={generateBtnStyle} onClick={generateKeys} disabled={loading}>
        {loading ? "Generating…" : "Generate key pair"}
      </button>

      {error && <div style={{
    fontSize: "13px",
    color: "#dc2626",
    padding: "8px 12px",
    background: "#fef2f2",
    borderRadius: "6px",
    border: "1px solid #fecaca"
  }}>
          {error}
        </div>}

      {(signingKey || publicKey) && <>
          <div>
            <div style={labelStyle}>Signing key (private)</div>
            <div style={fieldStyle}>{signingKey || "—"}</div>
            <div style={{
    display: "flex",
    gap: "6px",
    marginTop: "6px",
    alignItems: "center"
  }}>
              <button style={copyBtnStyle(copied["signing"])} onClick={() => copyToClipboard(signingKey, "signing")}>
                {copied["signing"] ? "Copied!" : "Copy"}
              </button>
              <span style={{
    fontSize: "11px",
    color: "#dc2626",
    fontWeight: 500
  }}>
                ⚠ Store this securely — never share it.
              </span>
            </div>
          </div>

          <div>
            <div style={labelStyle}>Public key (verify key)</div>
            <div style={fieldStyle}>{publicKey || "—"}</div>
            <div style={{
    display: "flex",
    gap: "6px",
    marginTop: "6px",
    alignItems: "center"
  }}>
              <button style={copyBtnStyle(copied["public"])} onClick={() => copyToClipboard(publicKey, "public")}>
                {copied["public"] ? "Copied!" : "Copy"}
              </button>
              <span style={{
    fontSize: "11px",
    color: "var(--muted-text-color, #6b7280)"
  }}>
                Paste this into the Anchorage Digital web dashboard when creating an API key.
              </span>
            </div>
          </div>
        </>}
    </div>;
};

Before setting up API keys for sandbox or production, review:

* API permission groups
* Wealth manager master API key
* Shared API key (for Anchorage Digital)
* Request signing
* Sandbox testing considerations

## API permission group

Configure permissions before generating an API key.

<Steps>
  <Step title="Generate an API key">
    Generate an API access key in the [Anchorage Digital web dashboard](https://anchoragelogin.com/) under the API 2.0 section. Save the key securely as keys are not recoverable.
  </Step>

  <Step title="Create permission group">
    Scroll to API permission groups and select 'Create a new group'
  </Step>

  <Step title="Name the group and enable the following permissions">
    | Permission                     | Enable? | Notes                                                                                                                                                     |
    | :----------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | Initiate withdrawal            | No      | Not required — withdrawals occur from vaults/wallets, not ledgered accounts.                                                                              |
    | Read subaccounts               | **Yes** | Read all balances and transactions on the wealth management ledger.                                                                                       |
    | Write subaccounts              | **Yes** | Create transactions on the wealth management ledger.                                                                                                      |
    | Execute trades                 | **Yes** | Trade from ledger balances. If not visible, the user is not an enabled trader.                                                                            |
    | Read trades                    | **Yes** | Read all trades and trade settlements. Select **All trades on the org**. If not visible, contact your account representative to enable trade permissions. |
    | Onboarding                     | **Yes** | Enables API-based client onboarding.                                                                                                                      |
    | Read deposit attribution       | **Yes** | Access past and current deposit attributions.                                                                                                             |
    | Configure webhooks             | **Yes** | Set up webhook notifications.                                                                                                                             |
    | Read vault                     | **Yes** | Read balances across all wallets. Select **All vaults**.                                                                                                  |
    | Create new address             | **Yes** | Create deposit wallets for account funding.                                                                                                               |
    | Transfer                       | No      | Not needed for wealth management integration.                                                                                                             |
    | Propose and accept settlements | No      | Not needed for wealth management integration.                                                                                                             |
    | Authorize settlements          | No      | Not needed for wealth management integration.                                                                                                             |
  </Step>
</Steps>

<Note>
  After submitting the permission group, endorse the operation on the iOS app to achieve quorum. Anchorage Digital will then perform a risk review before the permission group can be used to create an API key.
</Note>

## Master API key generation

<Steps>
  <Step title="Generate a unique Ed25519 public/private key pair">
    <KeyPairGenerator />

    ```python theme={null}
    # https://pypi.org/project/PyNaCl/

    import nacl
    import nacl.signing
    import secrets

    seed = secrets.token_bytes(32)

    signing_key = nacl.signing.SigningKey(seed)

    print('Signing key:')
    print(signing_key.encode().hex())

    print('Public key:')
    print(signing_key.verify_key.encode().hex())
    ```
  </Step>

  <Step title="Create the API key">
    Select the permission group created above, and use the public key from step 1 to create your API key.

    <Warning>
      Copy the API key immediately as it will not be displayed again. If lost, revoke the key and generate a new one.
    </Warning>
  </Step>
</Steps>

<Tip>
  For read-only keys issued to third-party vendors (e.g., data aggregation, reconciliation), provision with read-only permissions only. Read-only keys do not require an Ed25519 key pair — use the "I don't want to provision a signing key" toggle when creating the key.
</Tip>

## Create the shared API key for Anchorage Digital

The shared API key allows Anchorage Digital to settle trades on behalf of the wealth manager. It is provisioned by the wealth manager but owned and managed by Anchorage Digital.

<Steps>
  <Step title="Navigate to the Developer API 2.0 page" />

  <Step title="Select the 'Shared API keys' tab in the top navigation" />

  <Step title="Accept the terms and conditions" />

  <Step title="Create the permission group">
    The permission group is pre-configured. Select the applicable options, then quorum approve the operation. Wait for Anchorage Digital to complete its risk review before proceeding.
  </Step>

  <Step title="Create the shared API key">
    This step also requires quorum approval and an Anchorage Digital risk review. No Ed25519 key pair is required — Anchorage Digital manages this key.
  </Step>

  <Step title="Confirm key creation is complete">
    In the API 2.0 keys table, verify the key status is green and marked **Unused** after Anchorage Digital approval.
  </Step>
</Steps>

## API testing

Read-only APIs can be tested directly in the reference docs using your sandbox API key. Production keys will not work in the sandbox environment.

For write APIs, generate a request signature outside of Postman or the reference docs.

**API signing:** see the [Request signing](/knowledge-base/platform/developers/request-signing) guide.

**Host URLs:**

| Environment | URL                                    |
| :---------- | :------------------------------------- |
| Sandbox     | `https://api.anchorage-staging.com/v2` |
| Production  | `https://api.anchorage.com/v2`         |

## Sandbox setup

Some steps only apply to production (e.g., onboarding, trading, settlement). Note the following before beginning sandbox testing:

* Verify you are onboarded to the sandbox iOS app and have web dashboard access. Onboarding details are sent by Anchorage Digital via email.
* Admin users must download the iOS app for quorum approvals and API key creation.

### Sandbox testnet assets

All sandbox activity uses testnet assets only.

| Mainnet asset | Recommended testnet asset |
| :------------ | :------------------------ |
| Bitcoin       | `BTC_S` (Signet)          |
| Ethereum      | `ETHHOODI` (Hoodi)        |
| USDC          | `USDANCHOL` (Hoodi)       |
| Solana        | `SOL_TD` (Devnet)         |
