Wallet / Auth·EVM · Solana · Bitcoin
Turnkey
Non-custodial signing infrastructure built on secure enclaves with policy-based authorization. Powers embedded wallets, server signers, and MPC-style approval flows across EVM, Solana, and Bitcoin.
- 01non-custodial embedded wallets
- 02server-side signers with policies
- 03regulated / compliance-heavy apps
- 04passkey-based auth
- 05agent and bot signing
- pnpm add @turnkey/react-wallet-kit @turnkey/sdk-server
| Variable | Scope | Description |
|---|---|---|
| NEXT_PUBLIC_TURNKEY_ORGANIZATION_ID | Client | Turnkey parent organization ID from the dashboard. |
| NEXT_PUBLIC_TURNKEY_AUTH_PROXY_CONFIG_ID | Client | Auth proxy config ID used by the React Wallet Kit to broker passkey/email/OAuth flows. |
| TURNKEY_API_PUBLIC_KEY | Server | Server-side API public key for the parent-org root user (used to authenticate server signers). |
| TURNKEY_API_PRIVATE_KEY | Server | Server-side API private key. P-256 hex-encoded; rotate via the dashboard. Never expose to the client. |
Use Turnkey for non-custodial signing with policy-based authorization. On the client, wrap the app in `<TurnkeyProvider config={{ organizationId, authProxyConfigId }}>` from `@turnkey/react-wallet-kit` and call `useTurnkey()` to read `clientState`, `authState`, and to invoke `loginWithPasskey()` / `loginWithEmail()` / `loginWithOAuth()`. For server signing, instantiate `Turnkey({ apiBaseUrl: 'https://api.turnkey.com', apiPublicKey, apiPrivateKey, defaultOrganizationId })` from `@turnkey/sdk-server` and call `apiClient().signTransaction(...)` or `signRawPayload(...)`. Define policies in the dashboard before going live — every signing op runs through them.
- ⚑All signing requests must be stamped with a P-256 API key; if your platform marshals JSON differently than the SDK expects, stamps will silently fail verification.
- ⚑Sub-organizations are the primary tenancy unit — create one per end user rather than putting all users under the parent org, otherwise policies don't isolate properly.
- ⚑Passkey enrollment requires `https://` plus a registered RP ID; localhost works only with the kit's localhost shim, and mobile webviews must allow WebAuthn.
- ⚑Bitcoin and Solana signing use different curve/hash conventions — verify you're using the correct `signWith` derivation path and payload encoding per chain.
- ⚑The auth proxy is rate-limited per project; bulk-onboarding flows should batch via the server SDK rather than hammering the proxy from the browser.