Skip to main content
OneShot GTM runs on your machine: a CLI and a dashboard that share one local data file. Your data lives in ~/.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/signup requires name, email, and phone; optional fields are signupContext, callWindow, and linkedinUrl. Accepted ICP matches enqueue the concierge play.
  • POST /api/triggers/cal-no-show requires name, email, company, missedAt, and rescheduleLink; optional fields are phone, whatTheyWanted, and linkedinUrl. Accepted ICP matches enqueue demo-no-show.
Valid matches return 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.

LinkedIn messaging

GTM uses the LinkedIn account you connect through OneShot. There is nothing else to set up: no separate outreach account, no LinkedIn webhook and no public callback. Connect LinkedIn on Setup signs you in for messaging and for profile research, back to back. GTM reads conversations through OneShot and sends what you send: invites, messages and replies. A human reply is matched to its prospect and stops that person’s cadences. See LinkedIn.