Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tkhq/sdk/llms.txt
Use this file to discover all available pages before exploring further.
@turnkey/sdk-server is the server-side SDK for interacting with the Turnkey API from a Node.js environment. Its primary use cases are:
- Standing up an Auth Proxy to forward signed requests from the browser to Turnkey without exposing server API keys to the client
- Executing server actions (Next.js Server Actions or equivalent) for flows like OTP, OAuth login, and sub-organization management
- Making direct API calls to Turnkey with full API key authorization
Use the proxy handler to keep your Turnkey API keys on the server. The browser SDK sends requests to your proxy endpoint, which forwards them to Turnkey after verifying the method is allowed.
Installation
npm install @turnkey/sdk-server
The Turnkey class (TurnkeyServerSDK)
The main entry point is the Turnkey class (exported as Turnkey, internally named TurnkeyServerSDK).
Instantiation
const { Turnkey } = require("@turnkey/sdk-server");
const turnkey = new Turnkey({
apiBaseUrl: process.env.NEXT_PUBLIC_BASE_URL,
defaultOrganizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID,
apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY,
apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY,
});
Turnkey API base URL (e.g., https://api.turnkey.com).
Your Turnkey parent organization ID.
Your Turnkey API private key. Keep this on the server — never expose it to the browser.
Your Turnkey API public key.
Configuration for polling activity results (timeout and interval).
Getting an API client
Call turnkey.apiClient() to get a TurnkeyApiClient instance stamped with your API credentials:
const apiClient = turnkey.apiClient();
// Call any Turnkey API method
const { wallets } = await apiClient.getWallets({
organizationId: "suborg-id",
});
You can optionally pass different API credentials to scope a specific client:
const apiClient = turnkey.apiClient({
apiPublicKey: "other-public-key",
apiPrivateKey: "other-private-key",
});
Proxy handlers
The proxy handlers expose a single endpoint that the browser SDK calls to forward signed requests to Turnkey. Only the methods listed in allowedMethods (or the built-in defaults) are accepted.
The default allowed methods are: oauth, createReadWriteSession, createSubOrganization, emailAuth, and initUserEmailRecovery.
Express
const express = require("express");
const { Turnkey } = require("@turnkey/sdk-server");
const app = express();
app.use(express.json());
const turnkey = new Turnkey({
apiBaseUrl: process.env.NEXT_PUBLIC_BASE_URL,
defaultOrganizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID,
apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY,
apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY,
});
const turnkeyProxyHandler = turnkey.expressProxyHandler({});
app.post("/apiProxy", turnkeyProxyHandler);
app.listen(3000);
To restrict which methods are proxied, pass an allowedMethods array:
const handler = turnkey.expressProxyHandler({
allowedMethods: ["createSubOrganization", "oauth"],
});
Next.js
Use nextProxyHandler for Next.js API routes:
import { Turnkey } from "@turnkey/sdk-server";
import type { NextApiRequest, NextApiResponse } from "next";
const turnkey = new Turnkey({
apiBaseUrl: process.env.NEXT_PUBLIC_BASE_URL!,
defaultOrganizationId: process.env.NEXT_PUBLIC_ORGANIZATION_ID!,
apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY!,
apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY!,
});
export default turnkey.nextProxyHandler({});
Server actions
@turnkey/sdk-server exports a server object containing ready-to-use server actions for common flows. These are designed to run in a Next.js Server Actions context but can be adapted to any server environment.
import { server } from "@turnkey/sdk-server";
server.sendOtp
Send an OTP to a user’s email address or phone number.
const response = await server.sendOtp({
contact: "user@example.com",
otpType: "OTP_TYPE_EMAIL",
appName: "My App",
});
// response.otpId — use this to verify the OTP
server.verifyOtp
Verify an OTP code and receive a verification token.
const response = await server.verifyOtp({
otpId: "otp-id",
otpCode: "123456",
});
// response.verificationToken — use this with otpLogin
server.otpLogin
Complete a login flow using an OTP verification token.
const response = await server.otpLogin({
suborgID: "suborg-id",
verificationToken: "token",
publicKey: "ephemeral-public-key",
});
// response.session — the signed session JWT
server.oauthLogin
Complete an OAuth login using an OIDC token from a provider.
const response = await server.oauthLogin({
suborgID: "suborg-id",
oidcToken: "id-token-from-provider",
publicKey: "ephemeral-public-key",
});
// response.session — the signed session JWT
server.createSuborg
Create a new sub-organization for a user. Automatically creates Ethereum and Solana wallet accounts by default.
const response = await server.createSuborg({
email: "user@example.com",
// or phoneNumber: "+15555550100"
// passkey: { ... } — passkey attestation
// oauthProviders: [ ... ] — OAuth provider details
});
// response.subOrganizationId
server.getSuborgs
Look up existing sub-organizations by a filter (email, phone number, public key, etc.).
const { organizationIds } = await server.getSuborgs({
filterType: "EMAIL",
filterValue: "user@example.com",
});
server.getOrCreateSuborg
Find existing sub-organizations matching the filter, or create a new one if none are found. This is the recommended action for unified login/signup flows.
const { subOrganizationIds } = await server.getOrCreateSuborg({
filterType: "EMAIL",
filterValue: "user@example.com",
additionalData: {
email: "user@example.com",
},
});
server.getUsers
Retrieve users within an organization.
const { users } = await server.getUsers({
organizationId: "suborg-id",
});
server.createOauthProviders
Link additional OAuth providers to an existing user.
const response = await server.createOauthProviders({
organizationId: "suborg-id",
userId: "user-id",
oauthProviders: [
{ providerName: "Google", oidcToken: "id-token" },
],
});
server.sendCredential
Send an email authentication credential (magic link / email auth flow).
await server.sendCredential({
email: "user@example.com",
targetPublicKey: "ephemeral-public-key",
suborgID: "suborg-id",
emailCustomization: { appName: "My App" },
});
Client classes
TurnkeyServerClient
A low-level client that extends TurnkeySDKClientBase. Provides access to all Turnkey API methods. Constructed with a TurnkeySDKClientConfig that includes a stamper.
import { TurnkeyServerClient } from "@turnkey/sdk-server";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
const client = new TurnkeyServerClient({
stamper: new ApiKeyStamper({
apiPublicKey: "your-public-key",
apiPrivateKey: "your-private-key",
}),
apiBaseUrl: "https://api.turnkey.com",
organizationId: "your-org-id",
});
TurnkeyApiClient
TurnkeyApiClient extends TurnkeyServerClient and is the concrete class returned by turnkey.apiClient(). It is the recommended way to make authenticated API calls from the server:
const apiClient = turnkey.apiClient();
// All Turnkey API methods are available
const { subOrganizationId } = await apiClient.createSubOrganization({ ... });
const { wallets } = await apiClient.getWallets({ organizationId: "..." });
const { session } = await apiClient.stampLogin({ ... });