Repository navigation
Expand file tree
/
Copy path.env.example
More file actions
176 lines (154 loc) · 7.7 KB
/
Copy path.env.example
File metadata and controls
176 lines (154 loc) · 7.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# OutreachGraph environment.
#
# Every environment (local / staging / production) MUST have its own values for
# all of these. Production customer data is never copied into staging
# (PRD §1.1 "Environment Model").
# ---------------------------------------------------------------- database
# Local development defaults to a file if unset.
# Postgres in production (the app refuses to start on anything else there);
# a SQLite file for local development and tests. Unset outside production
# means file:./local.db. TURSO_* settings are retired: the data moved to
# Postgres on 2026-09-25.
DATABASE_URL=file:./local.db
# ------------------------------------------------------------------ runtime
NODE_ENV=development
PORT=8080
APP_VERSION=0.1.0
# Reported by `/` and `/health/live`, so a deploy can be identified without the
# dashboard. On Railway this is taken from RAILWAY_GIT_COMMIT_SHA automatically;
# set it only when deploying some other way.
COMMIT_HASH=
# --------------------------------------------------------------------- auth
# The API refuses to start in production without this.
API_TOKEN=
# Used to hash emails before they are stored as suppression match keys.
# Changing it orphans every existing hashed_email key, so rotate deliberately.
SUPPRESSION_HASH_SALT=
# ---------------------------------------------------------------- providers
# Absent keys simply disable that provider in the waterfall; the pipeline runs
# end to end on the fixture provider with none of them set.
APOLLO_API_KEY=
PDL_API_KEY=
GITHUB_TOKEN=
# Finds a lead's photo (and their LinkedIn profile URL, as research) by
# searching their name, title and company. One paid image search per person.
# Optional: crawls, GitHub, social profiles and Gravatar also supply pictures
# without image-search credits. LinkedIn image search requires this key.
VALUESERP_API_KEY=
# Idea Generator "Build it": chovy.com campaign hand-off (same value as chovy's CAMPAIGN_SECRET).
CHOVY_CAMPAIGN_SECRET=
# CHOVY_URL=https://chovy.com
# Ceiling on photo lookups per workspace per day. Default 300.
PHOTO_LOOKUPS_PER_DAY=
BLUESKY_IDENTIFIER=
BLUESKY_APP_PASSWORD=
X_API_KEY=
X_API_SECRET=
# ---------------------------------------------------------------------- LLM
# Never exposed to the browser, and never included in a model prompt alongside
# customer OAuth tokens (PRD §34).
#
# Optional. Unset, the composer is disabled: signals, resolution, scoring and
# the approval queue all still run, and the reviewer writes the message. It is
# never consulted for a policy, identity or scoring decision (PRD §1.1.8).
ANTHROPIC_API_KEY=
# Overrides the default model (claude-opus-5).
ANTHROPIC_MODEL=
# The fallback chain, tried in this order: anthropic -> openai -> gemini.
# Each key is independently optional; whichever are set become the chain, and a
# provider is only skipped when it reports that it is out of budget. A capped
# key that regains access rejoins at the front with no redeploy.
OPENAI_API_KEY=
# Overrides the default model (gpt-5.5). No moving "latest" alias exists for
# the reasoning line, so bumping a generation is a config change, not a deploy.
OPENAI_MODEL=
GEMINI_API_KEY=
# Overrides the default model (gemini-flash-latest).
GEMINI_MODEL=
# -------------------------------------------------------------------- email
# Account email, notifications, and outreach for any workspace that has not
# connected a mailbox of its own.
#
# Optional. Unset, verification links are written to the container log instead
# of being sent, so a fresh checkout can still complete a signup. Sending
# requires BOTH values; EMAIL_FROM must be on a domain verified with Resend.
RESEND_API_KEY=
EMAIL_FROM=
# Public origin used to build links that land in someone's inbox. Without it
# links point at localhost, which is correct locally and wrong in production.
APP_URL=
# Encrypts credentials a workspace hands us — today, the SMTP password for the
# mailbox it sends outreach from.
#
# 32 bytes, base64 or hex. Generate one with:
# bun -e "console.log(require('node:crypto').randomBytes(32).toString('base64'))"
#
# Unset, connecting a mailbox is refused rather than stored in the clear, and
# outreach falls back to the platform sender above. Changing it after mailboxes
# are connected makes them unreadable — every affected workspace reads as
# disconnected and has to reconnect, which is deliberate: a silent failure to
# send is worse than an obvious one.
SECRET_ENCRYPTION_KEY=
# ---------------------------------------------------------------- listening
# Public feeds searched for each campaign's own keywords. This is the only
# intake that does not start from a company: it finds the person from what they
# said, which is the only way to reach buyers with no engineering blog and no
# GitHub profile.
#
# **Where** a campaign listens is not configured here. Subreddits and feed URLs
# are targeting, they belong to the campaign that searches them, and they are
# edited per product on the setup screen (or via
# `PUT /api/v1/campaigns/:id/listening`). They lived in this file until
# migration 0012 and should not come back: one deployment serves many
# workspaces, so a single set of subreddits could suit at most one of them.
#
# What remains here is infrastructure — how to reach a network, not which
# communities to read.
# Reddit blocks generic and absent user agents, and the rejection arrives as a
# 429 that reads like a rate limit. Override only if you registered your own.
REDDIT_USER_AGENT=
# Optional. Public listings need no credentials but are metered per client;
# register an OAuth app for anything beyond a light poll.
REDDIT_ACCESS_TOKEN=
# Nostr relays. Defaults to two that implement NIP-50 search; relays without it
# stream recent notes instead and are filtered locally.
LISTEN_NOSTR_RELAYS=
# ----------------------------------------------------------------- payments
# CoinPayPortal, which sells prospect credits. All three or none: a client
# holding only two of them fails at the moment a customer clicks Buy, so the
# server refuses to construct one unless the set is complete, and /billing then
# reports honestly that credits are not for sale on this deployment.
COINPAY_API_KEY=
COINPAY_BUSINESS_ID=
# Signs webhooks. `payment.confirmed` is what actually grants credits, so an
# absent or wrong secret means paid-for credits silently never arrive.
COINPAY_WEBHOOK_SECRET=
# Override only when pointing at a staging portal.
COINPAY_BASE_URL=
# CoinPayPortal OAuth application credentials — a *different* thing from the
# payment keys above, and the mistake is easy to make because both start `cp`.
#
# cp_live_… / cp_test_… + 32 hex → a merchant API key. Creates payments.
# cp_… (24 hex) / cps_… (48 hex) → an OAuth client id and secret.
#
# The OAuth pair authenticates "sign in with CoinPay" and grants only
# openid/profile/email/did/wallet:read. It carries no payment authority at all:
# `isApiKey()` on the portal side rejects it, so putting one in
# COINPAY_API_KEY fails at the moment a customer clicks Buy rather than at boot.
#
# Nothing reads these yet. They are recorded so the two are not confused.
COINPAY_OAUTH_CLIENT_ID=
COINPAY_OAUTH_CLIENT_SECRET=
# Where CoinPayPortal should send those webhooks. Defaults to APP_URL, which is
# right in production because the API and the PWA share a hostname.
API_URL=
# -------------------------------------------------------------------- queue
# Optional until queued jobs need durability.
REDIS_URL=
# ------------------------------------------------------------------- worker
WORKER_TICK_MS=60000
# Crawl gateway (@profullstack/x402-gateway): AI training crawlers pay $1/day over
# x402. A SCOPED CoinPay key (payments:create) and the EVM address that receives
# the USDC. Unset = crawlers still get 402, nothing sold.
COINPAY_X402_KEY=
CRAWL_PAY_TO=