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 chain-specific signing keys from this secret, scoped to your project ID, environment, and target chain. A single secret can be safely reused across chains within a project.
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",
    signer: {
        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",
    { signer: { type: "server", secret: process.env.CROSSMINT_SIGNER_SECRET } }
);

HKDF-SHA256 Key Derivation Tool

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 chain-specific signing keys from it — 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 chain-specific private keys from this master secret using HKDF-SHA256, scoped to your project ID, environment, and target chain:
key = HKDF-SHA256(
  ikm:  <master secret>,
  salt: "crossmint",
  info: "<projectId>:<environment>:<chain>-<algorithm>"
)
The projectId and environment are extracted automatically from your server API key by the SDK — the same master secret produces entirely different signing keys per project, environment, and chain. This means a single secret can be safely reused across chains within a single project. 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.