toolzer Internal Docs
API

Environment variables

Derived from apps/api/src/configs/index.ts, the Zod schema validated once at boot (validateEnv, called from apps/api/src/main.ts). If validation fails, the process logs service_start_failed and exits — nothing here is silently ignored except the variables explicitly marked optional below.

A handful of variables are read directly via process.env outside this schema — listed separately at the bottom.

Core

VariableDefaultRequired
PORT2626No
NODE_ENVdevelopmentNo — one of development, production, test
LOG_LEVELinfoNo — a LogLayer LogLevel value
SERVER_URLhttp://localhost:2626No
APP_URLhttp://localhost:3000No — dashboard base URL used to build links (e.g. password-reset emails) that must point at the app, not this API
WORKER_HOSThttp://localhost:8000No — base URL for the Python worker (apps/worker); see apps/api/src/utils/buildUrl.ts
MINTER_HOSTunsetYes in production — browser-minter health endpoint; /ready requires its baked build commit to match the API and worker
PLATFORM_ADMIN_EMAILSunsetNo — comma-separated emails promoted to platform staff at boot (db/promoteAdmins.ts). Grant-only: removing an email here does not demote it.

Auth

VariableDefaultRequired
TOOLZERHUB_API_KEYcommitted legacy compatibility valueNo — a non-empty override shorter than 32 characters fails production boot
TOOLZERHUB_API_PREVIOUS_KEYunsetNo — one outgoing key accepted only during a staged Actor/client rotation
JOBS_ID_SECRETsame committed compatibility valueNo — keep any override stable so existing opaque job IDs remain decodable
ACTOR_TELEMETRY_API_KEYunset (falls back to legacy shared keys)No — deprecated compatibility for older Actor builds; remove after the fleet uses admin-created keys

TOOLZERHUB_API_KEY and JOBS_ID_SECRET deliberately share a committed compatibility default so the published Actor fleet and existing job IDs survive deployments without secret-store setup. Empty environment values use that default; non-empty overrides must contain at least 32 characters in production. TOOLZERHUB_API_PREVIOUS_KEY provides one explicit overlap window and must be cleared after the fleet moves. Keep any JOBS_ID_SECRET override unchanged. See auth-and-credits.md for the compatibility boundary and deployment.md for the release preflight.

Active API keys created by a current platform admin can write Actor telemetry; ordinary workspace keys cannot. ACTOR_TELEMETRY_API_KEY remains as a deprecated compatibility credential for older Actor builds: when set, it is accepted alongside admin-created keys; when unset, the current and previous legacy shared keys are accepted instead. Remove this compatibility boundary in a future edition after the published fleet has rotated.

Postgres

VariableDefaultRequired
POSTGRES_HOSTpostgresNo
POSTGRES_PORT5432No
POSTGRES_PASSWORD""No (but an empty password is very unlikely to work against a real deployment)

User and database name are hardcoded in apps/api/src/db/postgres.ts, not configurable via env.

ClickHouse (optional analytics)

VariableDefaultRequired
CLICKHOUSE_URLhttp://clickhouse:8123No
CLICKHOUSE_PASSWORD""No — ClickHouse recording is entirely gated on this being non-empty (shouldRecordClickHouseInsight, apps/api/src/observability/apiRequestInsight.ts). Unset, main.ts logs dependency_disabled and skips ClickHouse schema setup entirely.

User and database name are hardcoded in apps/api/src/db/clickhouse.ts.

OpenTelemetry

VariableDefaultRequired
OTEL_EXPORTER_OTLP_ENDPOINTunsetNo — leaving this unset disables OTLP export entirely (e.g. local dev without a collector)
OTEL_SERVICE_NAMEapiNo — see note below
OTEL_RESOURCE_ATTRIBUTESunsetNo

Note: OTEL_SERVICE_NAME's schema default is "api", but apps/api/src/observability/tracing.ts sets process.env.OTEL_SERVICE_NAME ||= "core-api" as a local-dev fallback before the schema is parsed (this module is preloaded ahead of main.ts) — docker-compose.yml sets it explicitly to api in a real deployment.

Sentry (optional)

VariableDefaultRequired
SENTRY_DSNunsetNo — Sentry is only initialized when this is set

Upstream providers

VariableDefaultRequired
RAPIDAPI_KEY""No
TIK_API""No — single TikHub API key backing every TikHub-proxied platform (TikTok Shop, TikTok, Reddit, Threads, LinkedIn Pro, ...); there is only one TikHub account/key, not one per platform

Evomi proxy (optional)

VariableDefaultRequired
PREMIUM_PROXY_PROVIDERdecodoNo
EVOMI_DC_USERunsetNo
EVOMI_DC_PASSunsetNo
EVOMI_RESI_USERunsetNo
EVOMI_RESI_PASSunsetNo

Used by the Apify Store sweep (apps/api/src/jobs/evomi-proxy.ts): datacenter credentials first, residential as fallback. With none set, the sweep goes direct.

Vantage

VariableDefaultRequired
VANTAGE_ENABLEDfalseNo — gates schema migration at boot and the background snapshot scheduler. /app routes stay mounted either way; with this off they simply have no tables to read.

Raw response archive

VariableDefaultRequired
RAW_ARCHIVE_ENABLEDfalseNo
RAW_ARCHIVE_ZSTD_LEVEL12No — integer 1–22
RAW_ARCHIVE_MAX_RECORDS500No — a batch flushes when it hits this many records, or the byte limit, or the age limit, whichever comes first
RAW_ARCHIVE_MAX_BATCH_BYTES4194304 (4 MiB)No
RAW_ARCHIVE_MAX_AGE_MS1800000 (30 min)No
RAW_ARCHIVE_MAX_BUFFER_BYTES67108864 (64 MiB)No — ceiling across all per-dataset buffers combined, not per buffer

Storage

STORAGE_PROVIDER is required with no default — it must be exactly local or cloudflare_r2 (a Zod discriminated union, apps/api/src/configs/index.ts).

VariableDefaultRequired
STORAGE_PROVIDERnoneYes — local or cloudflare_r2
LOCAL_STORAGE_DIR.data/objectsNo — used when STORAGE_PROVIDER=local
CLOUDFLARE_ACCOUNT_IDunsetYes, only if STORAGE_PROVIDER=cloudflare_r2 or LLM_PROVIDER=cloudflare
R2_ACCESS_KEY_IDnoneYes, only if STORAGE_PROVIDER=cloudflare_r2
R2_SECRET_ACCESS_KEYnoneYes, only if STORAGE_PROVIDER=cloudflare_r2

R2 bucket name is hardcoded in apps/api/src/storage/r2-store.ts, not configurable via env.

Email

VariableDefaultRequired
RESEND_EMAIL_TOKENunsetNo — unset disables outbound email rather than failing boot; see isEmailConfigured()

Incoming support mail additionally requires RESEND_WEBHOOK_SECRET and EMAIL_FORWARD_TO. See support email forwarding for the receiving webhook and activation steps.

Email uses the Resend Send Email API. The sender domain in email.service.ts must be verified in Resend. That file defines separate security and onboarding senders, a default support sender, and the reply address. Keep the reply address connected to a monitored inbox.

Read directly (not part of the validated configs/ schema)

These are read via process.env at the point of use rather than through envSchema/getEnv(), so a typo in one of these is not caught at boot the way the schema-validated variables above are.

VariableDefaultRead in
OTEL_SDK_DISABLEDunsetapps/api/src/observability/tracing.ts — set to "true" to force-disable the OTel SDK even if OTEL_EXPORTER_OTLP_ENDPOINT is set
SHUTDOWN_DRAIN_MS20000apps/api/src/main.ts — how long /health reports draining before shutdown proceeds, on SIGTERM/SIGINT only
SHUTDOWN_FORCE_EXIT_MS45000apps/api/src/main.ts — hard exit timeout if graceful shutdown hangs

Image build manifest

GIT_COMMIT and BUILD_TIME are Docker build arguments, not runtime variables. Each image writes them to a root-owned read-only /app/.build-info.json during the build; /health reads that manifest. Stack environment values cannot alter the identity reported by a running task.

On this page