Node.js examples guide
The full source is at GitLab sdk/server/node (repository access requires permission).
These examples show calling the API and receiving callbacks in various frameworks, with no chat web UI: for chat in the browser, use a client SDK; the chat demos of the Go and Python server SDKs are a different kind of example. The current version is 1.0.7, published on npm, so projects just install @deeprespond/im-server-sdk@1.0.7 with npm, or use a local tgz built from source. It needs Node.js 22.17 or later; projects can use npm, and only building from source needs pnpm. The SDK supports both ESM and CommonJS, and the example source below is TypeScript ESM.
If you just want an API call working first, the complete JavaScript example in the quickstart is enough, with no repository access needed. This page explains how to run the repository's scripts and framework examples in your own project; the npm package doesn't include them.
Optional: build a local package
From the root of the full repository:
cd sdk/server/node
pnpm install --frozen-lockfile
pnpm build
pnpm pack --pack-destination /tmpThis produces /tmp/deeprespond-im-server-sdk-1.0.7.tgz, containing only the build output (dist) and the SDK README, without examples; after the source changes, rebuild, pack and install again. On Windows, use an output directory you can write to; /tmp isn't a path every platform has. pnpm build doesn't run the full release checks, which need the full repository.
Running in a standalone project
Create a new ESM project and copy client.ts and import-users.ts from the repository's sdk/server/node/examples/ into its src directory (the paths below assume this layout):
mkdir im-node-example
cd im-node-example
npm init -y
npm pkg set type=module
npm install @deeprespond/im-server-sdk@1.0.7
npm install --save-dev typescript @types/node@22
mkdir srcThen compile. The .js imports in the source resolve to the TypeScript files under NodeNext rules:
npm exec -- tsc --module NodeNext --moduleResolution NodeNext --target ES2022 \
--strict --esModuleInterop --skipLibCheck --outDir dist src/client.ts src/import-users.tsDon't run node examples/*.ts directly: the sources import ./client.js, and the Node.js runtime won't turn that into client.ts for you. In PowerShell, join multi-line commands into one line and set environment variables with $env:NAME='value'.
You can also put the app config below in .env and start with node --env-file=.env dist/import-users.js users.jsonl; don't commit .env. Environment variables must be loaded before the client is created.
App config
client.ts only reads the environment variables below; use the server credentials of one app:
export IM_BASE_URL='https://im.example.com'
export IM_ORG_NAME='组织名'
export IM_APP_NAME='应用名'
export IM_CLIENT_ID='替换为 Client ID'
export IM_CLIENT_SECRET='替换为 Client Secret'IM_BASE_URL defaults to https://api.example.com and the others to empty, all just placeholders; in the AppKey, the parts before and after # are the org name and app name. Credentials stay on the back end only; never put them in code, browsers, logs or the repository. The SDK calls APIs as the app administrator, so your own endpoints must still check the current user and their permissions. An admin recall isn't a user recall, and the admin view of history isn't what a user can see; downloading attachments only fetches the content and doesn't set safe content types and download headers on your HTTP responses.
Choosing an example
| File | What it does, and what it needs |
|---|---|
client.ts | The shared DRClient; importing it sends no requests, and the first API call fetches the App Token |
import-users.ts | Creates users in bulk from a JSONL file, changing app data; check the target app before running |
send-message.ts | First sends a text from system to alice, then uploads banner.png from the current directory and sends it as an image; needs the user to exist and the image to be present |
login-ticket.ts | Exports imLoginTicket(username), not a standalone command; called by your back end after a successful business sign-in, and can create the IM user automatically |
callback-fastify.ts | Fastify 5 with in-memory nonces and de-duplication, listening on /im/callback at port 3000; for a single instance |
callback-express.ts | Express 4/5 + ioredis, listening on port 3000; the signed route must come before express.json() |
callback-nestjs.ts | NestJS on the Express platform with rawBody: true, listening on port 3000; not a complete business system |
nextjs/ | A route example for the Next.js nodejs runtime, integrated into a Next project's directories; it can't run on its own with node |
For example, create your own test JSONL file and import it (this really writes data, so only run it against a test app):
printf '%s\n' '{"username":"demo_import_alice","nickname":"测试用户"}' > users.jsonl
node dist/import-users.js users.jsonlCheck failed items by code; already_exists doesn't mean the whole batch failed. For the other examples, copy them into src and swap the entry file in the compile command above. The directory you run send-message in must contain banner.png, or the text may be sent while the image fails; in real code, handle each step's result. Scripts call im.close() when done; long-running back-end processes reuse one client and close it on shutdown.
Running callbacks locally
Using Fastify as the minimal example, copy callback-fastify.ts into src:
npm install fastify@5
npm exec -- tsc --module NodeNext --moduleResolution NodeNext --target ES2022 \
--strict --esModuleInterop --skipLibCheck --outDir dist src/callback-fastify.ts
export IM_CALLBACK_ENDPOINT_ID='回调地址ID'
export IM_CALLBACK_SECRET='回调签名密钥'
node dist/callback-fastify.js- In the console, create an endpoint pointing to an
/im/callbackthe IM service can reach, and save the ID and secret. - Start the receiver with these two variables, then verify the endpoint in the console and turn on the event subscriptions you need.
- Perform a business action and confirm the event reaches the handler; ordinary JSON requests you send yourself have no signature and don't prove callbacks work.
This example only registers group.members_added; the Express example also shows message.sent, user.created and the message.before_send sync hook. Fastify listens on the local address by default; if the IM service is remote, set up a reverse proxy or tunnel on your machine, or change the listen address. The browser opening the port doesn't mean the IM service can reach it. The Express example also needs express@5, ioredis@5 and @types/express, with REDIS_URL configured (default redis://127.0.0.1:6379); it doesn't use any other Redis address automatically. The NestJS example also needs @nestjs/common, @nestjs/core, @nestjs/platform-express, reflect-metadata and rxjs; with several processes, switch nonces and de-duplication to a shared Redis. These examples all use port 3000, so run one at a time, stopping with Ctrl+C before switching.
Key settings for other frameworks
| Framework | Dependencies and settings | Full integration |
|---|---|---|
| Express | Install express@5, ioredis@5 and @types/express; put the callback route before the JSON parser; have Redis ready before running | Express, Shared storage |
| NestJS | Use the Express platform with rawBody: true; set the JSON limit to 2 MiB; existing Nest projects keep their own TypeScript and decorator config | NestJS |
| Koa | Install koa and its types; keep the raw request body; pick dependencies for Koa 2 or 3 | Koa |
| Next.js | Add app/im/callback/route.ts and a shared handler module to an existing App Router project; choose the nodejs runtime, with several instances sharing Redis | Next.js |
The Next.js example is a route module and can't start as a plain Node.js script. To test it, run the full Next app and send signed requests to the actual HTTP route, rather than only checking that the TypeScript compiles.
Checks and troubleshooting
From the root of the full repository you can run make sdk-server-node-test and make sdk-server-node-integration; the latter needs the repository's test service running first. SDK tests, example compilation and real callback testing each need confirming separately.
For what was verified when npm 1.0.7 was released, see the release notes; when installing or testing fails, check versions, credentials, the network and the raw request body against FAQ and troubleshooting first.
| Symptom | Check |
|---|---|
| npm 404 | Whether the registry is https://registry.npmjs.org/ and the package name and version are right; if a private mirror hasn't synced, use the official registry or a local tgz |
| client.js not found | Compile the TypeScript with NodeNext and run the files in dist, not the example TS directly |
| 401 or invalid credentials | Whether the org, app, Client ID/Secret and API address belong to the same environment |
| Image sending fails partway | Whether banner.png is in the current directory, the user exists, and the file size and app policies allow it |
| Endpoint verification fails | Whether the receiver is running, the endpoint ID and secret match, the raw body is unchanged, the reverse proxy path is right, and the IM service can reach it |
| Redis ECONNREFUSED | REDIS_URL, the actual port, authentication and database; or start with the single-instance Fastify example |
| Duplicate events or instances disagreeing | Whether your business is idempotent and nonces and de-duplication use shared storage, rather than each process's memory |
For the full docs, see Node.js SDK.
