Stridee
Stridee Platform Docs

Quickstart

Install the CLI, receive and open your first webhook delivery on localhost, then point it at production.

You need an account. Fifteen minutes, no public URL, and no shared secret at any point.

1. Install the CLI and sign in

stridee puts real webhook deliveries on your local server — no tunnel, nothing exposed. Install it, sign this machine in, and approve the code it prints in the console.

Install
Reference

macOS and Linux, Intel and ARM.

One static binary, checked against the published SHA256SUMS and installed to ~/.stridee/bin — never a sudo prompt. If that directory is not on your PATH, the installer prints the line to add. Set STRIDEE_INSTALL_DIR to put it somewhere else.

stridee login
Reference

Sign this machine in by approving it in the console.

Prints a code and opens the console. Approve it there — check the code matches your terminal — and this machine is signed in.

There is no token. The CLI generates an Ed25519 keypair, sends only the public half, and your approval registers that half as a signing key on your account, listed under Keys as Made by the Stridee CLI. The private half stays in ~/.config/stridee/config.json, readable only by you — treat it like an SSH key.

Options
--device-name<NAME>

What the console calls this machine. Defaults to its hostname

Terminal
curl -fsSL https://download.stridee.com/install.sh | sh
stridee login

2. Start listening

For as long as this runs, your local server receives every delivery exactly as production would. On first run it makes an encryption key for this machine and tells you where the private half is:

stridee listen
Reference

Receive webhook deliveries and forward them to a local server.

Opens a signed connection to Stridee and becomes one more webhook endpoint on your account for as long as it runs. Every event your account emits is POSTed to your local server exactly as production receives it: the same sealed envelope and the same webhook-id, webhook-timestamp and webhook-signature headers. No tunnel, and nothing on your machine is exposed.

The CLI never decrypts anything, so your handler's own verify and decrypt code is what runs. On first use it makes a webhook key for this machine and writes the private half as PKCS#8 PEM, the format the console downloads, to ~/.config/stridee/. Pass --key to seal to a key your handler already loads instead.

Each delivery prints one line once Stridee has judged your handler's answer. Decrypted means it returned 2xx with the delivery's nonce in the body, which only something holding the private key can do.

Your production endpoints keep receiving deliveries while you listen: the listener gets a copy.

Options
-f, --forward-to<URL>Required

Where to POST each delivery, e.g. localhost:3000/webhooks

--key<KEY_ID>

Seal deliveries to a webhook key you already hold instead of making one

Terminal
stridee listen --forward-to localhost:3000/webhooks
First run
Made a webhook key for this machine. Point your handler's decrypt at:
  ~/.config/stridee/listen-0b6f2d14.pem

3. Write the handler

What arrives is a small cleartext envelope with the ciphertext in enc. It is standard JWE compact, so opening it is a library call rather than homegrown crypto.

Return a 2xx carrying {"nonce": …}. That echo is the difference between us knowing a server answered and knowing your service opened the body — see Confirming a delivery. Before production, add the signature check and dedupe — the full order is in Handling a delivery.

import { readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { createPrivateKey } from 'node:crypto';
import { compactDecrypt } from 'jose';

const key = createPrivateKey(readFileSync(join(homedir(), '.config/stridee/listen-0b6f2d14.pem')));

export async function handle(rawBody, res) {
  const { id, enc } = JSON.parse(rawBody);

  const { plaintext } = await compactDecrypt(enc, key);
  const event = JSON.parse(new TextDecoder().decode(plaintext));

  console.log(event.type, id);

  // The nonce came out of the ciphertext, so returning it proves you opened it.
  res.json({ nonce: event.nonce });
}

4. Send a ping

In another terminal:

stridee trigger ping
Reference

Send a ping to every running stridee listen on your account.

The same event the console's test button sends, delivered only to your listeners — never to production endpoints. Prints how each listener's handler answered.

Inside the envelope, your handler sees:

Nothing about it is a special case: it takes exactly the path a real event takes.

Terminal
stridee trigger ping
The plaintext inside a ping
{
  "id": "9f2c1e7a-4b83-4d21-9a6e-3c5f0d8b71a4",
  "type": "ping",
  "created": "2026-08-04T06:14:02Z",
  "webhook_id": "2d7b45c1-8e0a-4f36-b512-9c7d3a6e04f8",
  "nonce": "Kd4nWpLbEa9xTvRm2Cj7Lz0Bq2vNhCz7",
  "data": {}
}

5. Go live

Once the handler is deployed, give production its own key and endpoint.

  1. Add an encryption key on Webhooks. The pair is generated in your browser and the private half downloads straight to disk — confirm the download when asked, because a key whose private half may not exist anywhere cannot be assigned to an endpoint. Point your deployed handler at that file.
  2. Add your endpoint on Webhooks and choose that key. The URL has to be https:// and resolve to a public address. There is no verification step, and no secret comes back.
  3. Press Send ping. It shows the status code and timing, or which hop failed, and the ping appears on the event stream with every other event.

Prefer to mint the key yourself? It has to be X25519:

Webhooks covers the handler start to finish, and Encrypted deliveries covers the scheme and rotating a key without a gap.

Bring your own
openssl genpkey -algorithm x25519 -out stridee-enc.pem
openssl pkey -in stridee-enc.pem -pubout

Something wrong or missing on this page? Tell us in Discord. Need something the API doesn’t do yet? Request it on the roadmap.