This guide takes you from zero to a signed webhook landing in your terminal. You’ll create a tenant, add a user, and watch a tenant.users.invite event arrive - fully signed.
1. Get your API keys
Create a tenant
Every piece of data in Geldstuck is scoped to a tenant - think of a tenant as a workspace. Click New tenant , give it a name, and hit Create .
Copy your keys
You’ll see three secrets. Copy them now - the secret key and webhook secret are shown only once. GELDSTUCK_PUBLIC_KEY = pk_test_51H...
GELDSTUCK_SECRET_KEY = sk_test_51H...
GELDSTUCK_WEBHOOK_SECRET = whsec_xS...
Treat sk_test_... and whsec_... like database passwords. Never commit them. Store in your secrets manager.
2. Make your first request
Set your base URL and export your keys, then fetch your tenant profile to confirm the keys work.
https://api.geldstuck.com/v1
cURL
Node.js (fetch)
Python (requests)
curl https://api.geldstuck.com/v1/tenants/me \
-H "x-api-key: $GELDSTUCK_PUBLIC_KEY " \
-H "x-api-secret: $GELDSTUCK_SECRET_KEY "
You should see a JSON response like:
{
"tenantId" : "tnt_01HX3Z8MQW..." ,
"name" : "Acme Escrow" ,
"status" : "active" ,
"createdAt" : "2026-04-22T09:12:44.000Z"
}
3. Invite a user
Now create a user under your tenant. This triggers the tenant.users.invite webhook - which we’ll catch in the next step.
cURL
Node.js (fetch)
Python (requests)
curl https://api.geldstuck.com/v1/tenants/add-user \
-H "x-api-key: $GELDSTUCK_PUBLIC_KEY " \
-H "x-api-secret: $GELDSTUCK_SECRET_KEY " \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"email": "ada@example.com"
}'
Response:
{
"id" : "usr_01HX3ZAB..." ,
"name" : "Ada Lovelace" ,
"email" : "ada@example.com" ,
"tenantId" : "tnt_01HX3Z8MQW..." ,
"status" : "invited" ,
"createdAt" : "2026-04-22T09:13:02.000Z"
}
4. Receive your first webhook
Webhooks need a public URL we can POST to. For local development, expose your laptop with a tunnel - we recommend ngrok or Cloudflare Tunnel .
Start a tunnel to your local server
Copy the https://....ngrok-free.app URL.
Register it as a webhook endpoint
In the dashboard, go to Developers → Webhooks → Add endpoint . Paste the tunnel URL with your path, e.g. https://abc123.ngrok-free.app/webhooks, and subscribe to at least tenant.users.invite.
Trigger an event
Re-run the add-user call from step 3 - this emits tenant.users.invite to your endpoint.
Your endpoint receives a signed POST:
POST /webhooks HTTP / 1.1
Content-Type: application/json
X-Geldstuck-Event: tenant.users.invite
X-Geldstuck-Webhook-Id: evt_01HX3ZC...
Geldstuck-Signature: t=1745311982,v1=b8a7e1c4...
{
"id" : "evt_01HX3ZC..." ,
"type" : "tenant.users.invite" ,
"tenantId" : "tnt_01HX3Z8MQW..." ,
"data" : {
"userId" : "usr_01HX3ZAB..." ,
"email" : "ada@example.com"
},
"createdAt" : "2026-04-22T09:13:02.000Z"
}
5. Verify the signature
Never trust a webhook you haven’t verified. An attacker who knows your endpoint URL can forge events unless you check the signature.
Node.js (Express)
Python (Flask)
import express from "express" ;
import crypto from "crypto" ;
const app = express ();
app . post (
"/webhooks" ,
express . raw ({ type: "application/json" }),
( req , res ) => {
const header = req . headers [ "geldstuck-signature" ] as string ;
const [ tPart , v1Part ] = header . split ( "," );
const timestamp = Number ( tPart . split ( "=" )[ 1 ]);
const received = v1Part . split ( "=" )[ 1 ];
const expected = crypto
. createHmac ( "sha256" , process . env . GELDSTUCK_WEBHOOK_SECRET !)
. update ( ` ${ timestamp } . ${ req . body . toString () } ` , "utf8" )
. digest ( "hex" );
const ok =
expected . length === received . length &&
crypto . timingSafeEqual ( Buffer . from ( expected ), Buffer . from ( received ));
if (! ok ) return res . status ( 400 ). send ( "Invalid signature" );
const event = JSON . parse ( req . body . toString ());
console . log ( "Received" , event . type );
res . sendStatus ( 200 );
},
);
That’s the full loop - tenant → API call → signed webhook → verified handler.
What’s next?
KYC walkthrough Verify your first user with Geldstuck’s hosted identity flow.
Escrow walkthrough Create an escrow transaction and invite a counterparty.
Webhook events Full catalog of events you can subscribe to.
API reference Every endpoint, every parameter.