Getting started with Node SDK
Installation
There's an ES module for the Clerk Node SDK available under the @clerk/clerk-sdk-node npm package. Use `npm` or `yarn` to install the Clerk Node module.
1npm install @clerk/clerk-sdk-node
1yarn add @clerk/clerk-sdk-node
Set CLERK_API_KEY
The Node SDK will pick automatically the CLERK_API_KEY
vale from your environment variables. If your application is using .env files, create a file named .env.local in your application root, if it doesn't exist already, and add the below variable:
.env.localCLERK_API_KEY=test_asdf1234
Make sure you update this variable with the API key found in your Clerk instance dashboard under API Keys
Resource types
The following types are of interest to the integrator:
Resource | Description |
---|---|
Client | unique browser or mobile app |
Session | a session for a given user on a given client |
User | a person signed up via Clerk |
an email message sent to another user | |
SMS Message | an SMS message sent to another user |
The following types are not directly manipulable but can be passed as params to applicable calls:
Resource | Description | Usage |
---|---|---|
EmailAddress | email address, a user may have a primary & several secondary | email address id can be provided to `emails` sub-api to specify the recipient |
PhoneNumber | E.164 telephone number, a user may have a primary & several secondary | phone number id can be provided to `smsMessages` sub-api to specify the recipient |
Internal implementation details
This SDK is written in TypeScript and built with tsdx.
CJS, ESM, and UMD module builds are provided.
The http client used by the sdk is got.
All resource operations are mounted as sub-APIs on a Clerk
class and return promises that either resolve with their expected resource types or reject with the error types described below.
The sub-APIs are also importable directly if you don't want to go through the Clerk
class.
Available options and ENV vars
The following options are available for you to customize the behaviour of the Clerk
class.
Note that most options can also be set as ENV vars so that you don't need to pass anything to the constructor or set it via the available setters.
Option | Description | Default | ENV variable |
---|---|---|---|
apiKey | server key for api.clerk.dev | none | `CLERK_API_KEY` |
apiVersion | for future use, v1 for now | "v1" | `CLERK_API_VERSION` |
serverApiURL | for debugging / future use | "https://api.clerk.dev" | `CLERK_API_URL` |
httpOptions | http client options | {} | N/A |
For every option the resolution is as follows, in order of descending precedence:
- option passed
- ENV var (if applicable)
- default
Another available environment variable is CLERK_LOGGING
.
You can set its value to true
to enable additional logging that may be of use when debugging an issue.
httpOptions
The SDK allows you to pass options to the underlying http client (got) by instantiating it with an additional httpOptions
object.
e.g. to pass a custom header:
const sdk = new Clerk(apiKey, {httpOptions: {headers: { "x-unicorn": "rainbow" }}});
You can check the options the got client supports here.
Singleton
If you are comfortable with setting the CLERK_API_KEY
ENV variable and be done with it, the default instance created by the SDK will suffice for your needs.
ESM
import clerk from '@clerk/clerk-sdk-node';const userList = await clerk.users.getUserList();
Or if you are interested only in a certain resource:
import { sessions } from '@clerk/clerk-sdk-node';const sessionList = await sessions.getSessionList();
CJS
const pkg = require('@clerk/clerk-sdk-node');const clerk = pkg.default;clerk.emails.createEmail({ fromEmailName, subject, body, emailAddressId }).then((email) => console.log(email)).catch((error) => console.error(error));
Or if you prefer a resource sub-api directly:
const pkg = require('@clerk/clerk-sdk-node');const { clients } = pkg;clients.getClient(clientId).then((client) => console.log(client)).catch((error) => console.error(error));
Setters
The following setters are available for you to change the options even after you've obtained a handle on a Clerk
or sub-api instance:
If you have a clerk
handle:
clerk.apiKey = value
;clerk.serverApiUrl = value
;clerk.apiVersion = value
;clerk.httpOptions = value
;
If are using a sub-api handle and wish to change options on the (implicit) singleton Clerk
instance:
setClerkApiKey(value)
setClerkServerApiUrl(value)
setClerkApiVersion(value)
setClerkHttpOptions(value)
Custom instantiation
If you would like to use more than one Clerk
instance, e.g. if you are using multiple API keys or simply prefer the warm fuzzy feeling of controlling instantiation yourself:
ESM
import Clerk from '@clerk/clerk-sdk-node/instance';const clerk = new Clerk({ apiKey: 'top-secret' });const clientList = await clerk.clients.getClientList();
CJS
const Clerk = require('@clerk/clerk-sdk-node/instance').default;const clerk = new Clerk({ apiKey: 'your-eyes-only' });clerk.smsMessages.createSMSMessage({ message, phoneNumberId }).then((smsMessage) => console.log(smsMessage)).catch((error) => console.error(error));
Multi-session applications
If Clerk is running in multi-session mode, it's important to ensure your frontend sends the Session ID that is making the request.
Our middleware will look for a query string parameter named _clerk_session_id. If this parameter is not found, the middleware will instead choose the last active session, which may be subject to race conditions and should not be relied on for authenticating actions.
Node.js middleware
Optional session
This strategy allows you to detect whether or not there's an active session, and handle each case separately.
1import { withAuth } from '@clerk/clerk-sdk-node';23function handler(req, res) {4if (req.session) {5// do something with session.userId6} else {7// Respond with 401 or similar8}9}1011export default withAuth(handler);
1import { withAuth, WithAuthProp } from '@clerk/clerk-sdk-node';23function handler(req: WithAuthProp<NextApiRequest>, res: NextApiResponse) {4if (req.session) {5// do something with session.userId6} else {7// Respond with 401 or similar8}9}1011export withAuth(handler);
Required session
This strategy mandates that a session be available. If not, it returns a 401 (no body) and your handler is never called.
1import { requireAuth } from '@clerk/clerk-sdk-node';23function handler(req, res) {4// do something with session.userId5}67export default requireAuth(handler)
1import { requireAuth, RequireAuthProp } from '@clerk/clerk-sdk-node';23function handler(req: RequireAuthProp<NextApiRequest>, res: NextApiResponse) {4// do something with session.userId5}67export default requireAuth(handler)
Manual authentication
Authenticate a particular session
Highly recommended for authenticating actions.
import { sessions } from '@clerk/clerk-sdk-node';import Cookies from 'cookies';// Retrieve the particular session ID from a// query string parameterconst sessionId = req.query._clerk_session_id;// Note: Clerk stores the clientToken in a cookie// named "__session" for Firebase compatibilityconst cookies = new Cookies(req, res);const clientToken = cookies.get('__session');const session = await sessions.verifySession(sessionId, clientToken);
Authenticate the last active session
Using the last active session is appropriate when determining the user after a navigation.
import { clients, sessions } from '@clerk/clerk-sdk-node';// Note: Clerk stores the clientToken in a cookie// named "__session" for Firebase compatibilityconst cookies = new Cookies(req, res);const clientToken = cookies.get('__session');const client = await clients.verifyClient(sessionToken);const sessionId = client.lastActiveSessionId;const session = await sessions.verifySession(sessionId, clientToken);