~/.oneshot-gtm/ledger.sqlite. ONESHOT_GTM_HOME relocates the whole directory.
Secrets live in ~/.oneshot-gtm/.env (chmod 600).
The server is single-user and binds only to 127.0.0.1. The dashboard has no login and relies on that boundary. Keep unsigned intake endpoints private or protect them at your reverse proxy.
Trigger webhooks
Signups and missed demos enter through two webhooks. Two JSON endpoints feed warm product signals through the normal ICP filter and review queue:POST /api/triggers/signuprequiresname,email, andphone; optional fields aresignupContext,callWindow, andlinkedinUrl. Accepted ICP matches enqueue theconciergeplay.POST /api/triggers/cal-no-showrequiresname,email,company,missedAt, andrescheduleLink; optional fields arephone,whatTheyWanted, andlinkedinUrl. Accepted ICP matches enqueuedemo-no-show.
202, ICP rejections return 200 with accepted: false, and malformed JSON or fields return 400. Signups deduplicate by lowercase email; no-shows deduplicate by lowercase email + missedAt.
Set WEBHOOK_SECRET to authenticate both endpoints. Send X-Webhook-Signature: t=<unix-seconds>,v1=<hex>, where the hex value is an HMAC-SHA256 of <timestamp>.<raw JSON body>. A signed delivery is accepted for five minutes and only once. With the secret unset, both endpoints accept unsigned requests.