Skip to main content
Authorize transactions directly from a server environment using a Crossmint API key, and a secret provided by you. Signing happens entirely in-process with no external network call, making this the lowest-latency option available. Because this key lives as a secret in your infrastructure, enforcing regular rotations is recommended — for example, quarterly — to limit exposure in the event of a compromised environment, a departed employee, or an infrastructure incident. For a conceptual overview, see Server signer in the Wallet Signers guide. To learn how to register additional operational signers on an existing wallet, see Registering a signer.

Configuration

1

Generate a Signer Secret

You must generate a signer secret to ensure that no one — including Crossmint — can access or control your wallet. This secret:
  1. Must be either 64 hex characters (case-insensitive) or use the prefixed format xmsk1_<64-hex-chars>.
  2. Remains on your server and is never transmitted to Crossmint. The SDK derives a private/public keypair from it locally and uses public-key infrastructure (PKI) for authorization — only the public key is ever shared.
Generate and store this secret securely. This secret can grant full signing authority over the wallet.
Generate a secret using the tool below or programmatically, and store it as the CROSSMINT_SIGNER_SECRET environment variable on your server:
CROSSMINT_SIGNER_SECRET="xmsk1_<your-64-hex-character-secret>"
# OR
CROSSMINT_SIGNER_SECRET="<your-64-hex-character-secret>"

# EXAMPLE
CROSSMINT_SIGNER_SECRET="b62b473b3ba7d3d72bf7c3a397f1eb61c305a4193ce670dd056686c13d95bbaa"
The Crossmint SDK automatically derives signing keys from this secret, scoped to your project ID, environment, and chain type (EVM, Solana, or Stellar). A single secret produces the same derived address across all EVM chains within a project — you do not get a different key per EVM network.
2

Create a Wallet with a Server Signer

Pass type: "server" as the signer type when creating a wallet. The SDK handles key derivation and address resolution automatically.
import { CrossmintWallets, createCrossmint } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({
    apiKey: "<your-server-api-key>",
});
const crossmintWallets = CrossmintWallets.from(crossmint);

const wallet = await crossmintWallets.createWallet({
    chain: "base-sepolia",
    recovery: {
        type: "server",
        secret: process.env.CROSSMINT_SIGNER_SECRET,
    },
    alias: "my-server-wallet"
});
The alias parameter lets you retrieve the wallet later without storing the wallet address:
const wallet = await crossmintWallets.getWallet(
    "evm:alias:my-server-wallet",
    { chain: "base-sepolia" }
);
await wallet.useSigner({
    type: "server",
    secret: process.env.CROSSMINT_SIGNER_SECRET,
});

Signer Secret Generator

Use this tool to generate a master signer secret for your server-side or agent wallet environment. The secret is generated entirely in your browser — nothing is transmitted to any server.

Generate Your Own Key Programmatically

You can also generate a signer secret programmatically:
import { randomBytes } from "crypto";

function generateSignerSecret(): string {
  const bytes = randomBytes(32);
  const hex = bytes.toString("hex");
  return `xmsk1_${hex}`;
}

const secret = generateSignerSecret();
console.log(`CROSSMINT_SIGNER_SECRET="${secret}"`);

Under the Hood

A server signer is, at its core, a secret that gets deterministically mapped into a private key compatible with the underlying blockchain network. You provide a master secret, and the Crossmint SDK derives signing keys from it grouped by chain type — so a single secret works across all supported chains within a project.

How Key Derivation Works

A 32-byte (256-bit) random value serves as your master secret. The SDK derives private keys from this master secret using HKDF-SHA256, scoped to your project ID, environment, and chain type:
key = HKDF-SHA256(
  ikm:  <master secret>,
  salt: "crossmint",
  info: "<projectId>:<environment>:<chainType>-<algorithm>"
)
Where chainType is one of evm, solana, or stellar, and algorithm is secp256k1 (EVM) or ed25519 (Solana/Stellar). The projectId and environment are extracted automatically from your server API key by the SDK. Because derivation uses chain type rather than the specific network name, the same master secret produces the same signing key and address across all EVM chains (e.g., Base, Ethereum, Polygon) within a given project and environment. Solana and Stellar each derive their own distinct key.
Wallets created before the chain-type normalization may have been derived using the specific chain name (e.g., base-sepolia) instead of evm. The SDK automatically applies a legacy fallback for these wallets so existing addresses continue to resolve correctly.
You can derive the public address using Crossmint’s wallets SDK — see the derive-server-signer helper for reference.

How Are Server Signer Locators Derived

When referencing a server signer in API calls (for example, when submitting approvals or registering it as an operational signer), use the locator format server:<address>:
server:0x1234567890123456789012345678901234567890
The <address> is the public address derived from your signer secret for the target chain. The SDK computes this automatically when you use type: "server" — you only need the locator format when working with the REST API directly.