Node examples
Small programs that do what your backend does: keep the platform's copy of your profiles current, and sign users in. They use only what Node ships with (node:crypto, node:http and fetch), so there is nothing to install.
They are written in TypeScript that Node runs as it is. You need Node 22.18 or later (Node 24 and 26 work too). On an older Node, update it first: these files do not run there.
Copy them into your own code and adapt them. They are not a package to depend on, and they may change between releases of this kit.
| File | What it shows |
|---|---|
| profile-sync.ts | A client for profile sync: retries, batches, the paged reconciliation read (guide) |
| profile-lifecycle.ts | The whole life of a profile, run step by step against your sandbox site |
| user-token.ts | Signing a user token for a visitor or a profile owner (guide) |
| token-server.ts | The two token routes your pages call, each on its own server: your site's and your owner dashboard's |
tsconfig.json is only for the platform's own checks of these files. You do not need it.
Keys stay out of the code
Every key comes from the environment or from a file, never from the source:
- the secret key from a file that
MESSENGER_SECRET_KEY_FILEnames, or fromMESSENGER_SECRET_KEY; - the token signing key from a PEM file that
MESSENGER_TOKEN_KEY_FILEnames.
Nothing here prints a token or a key. Keep it that way in your own code: no token or key in logs, error messages or URLs.
Run the profile lifecycle
MESSENGER_API_URL=https://api.messenger.example \
MESSENGER_SECRET_KEY_FILE=$HOME/.config/messenger/secret-key \
node profile-lifecycle.ts
Use your sandbox site's secret key, sk_test_..., and your platform's API address, which starts with https://. The program refuses any other key, and plain http:// to anything but your own machine. It sends three invented profiles (example-lena, example-hugo and example-sofia) through every step of their life and checks each answer. It prints each step and the platform's answer, and stops with an error at the first answer it did not expect.
When it is done, example-lena and example-hugo stay on your site, and the partner console lists them on its Profiles page with the two rejections the walk-through caused on purpose. example-lena is owned by owner-lena, the token server's demo owner, so you can open the inbox as her (guide 5). To delete the example profiles again:
node profile-lifecycle.ts --remove
Running the walk-through again is safe: each run takes its versions from the clock, so they are higher than the last run's.
Sign users in
First make a key pair and upload its public half in the partner console (guide 1). Then run the token server with the invented demo users switched on:
MESSENGER_PUBLISHABLE_KEY=pk_test_... \
MESSENGER_TOKEN_KID=tk_... \
MESSENGER_TOKEN_KEY_FILE=$HOME/.config/messenger/token-key.pem \
EXAMPLE_DEMO_USERS=1 \
node token-server.ts
It starts two servers, because the two routes belong on two origins:
- your site's server, on
http://localhost:8787(PORTchanges it), answers only/messenger/token, a visitor's token for the messenger; - your owner dashboard's server, on
http://localhost:8788(DASHBOARD_PORTchanges it), answers only/messenger/inbox-token, an owner's token for the inbox.
Both listen on your own machine only. An origin matches only the same scheme, host and port, so http://127.0.0.1:8787 is a different origin from http://localhost:8787: use the address you list among the site's allowed origins (guide 1).
An inbox token opens the owner's conversations, so its route lives only on the dashboard's own origin, where no public page and no third-party script runs (guide 5).
EXAMPLE_DEMO_USERS=1 adds two invented sign-ins, set by the cookie session: demo-visitor on your site (a visitor, user ID user-1042) and demo-owner on your dashboard (a profile owner, user ID owner-lena). It works only with a sandbox site's publishable key, pk_test_.... Check that each route answers without showing the token:
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
-H 'Cookie: session=demo-visitor' http://localhost:8787/messenger/token
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
-H 'Cookie: session=demo-owner' http://localhost:8788/messenger/inbox-token
200 means it signed a token. With no cookie it answers 204 with no body: nobody is signed in. The messenger takes the empty answer as a guest, and the inbox's page script answers signout (guide 4, Your token route).
In your own servers, replace currentVisitor() and currentOwner() with your real session lookups and leave EXAMPLE_DEMO_USERS off.