> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asobeast.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration reference

> Every environment variable the asobeast API reads, with its default and its effect. AUTH_SECRET is required and must be at least 32 characters.

Every variable below is read by the API from `apps/api/.env`, or from the environment of the API container. Everything except `DATABASE_URL` and `AUTH_SECRET` has a working default.

<Warning>
  Three settings stop a deployment cold. `AUTH_SECRET` must be at least 32 characters or the API refuses to boot, and changing it signs out every user. Compose refuses to start when `POSTGRES_PASSWORD` or `AUTH_SECRET` is missing or empty from the root `.env`.
</Warning>

## Required

| Variable       | Default                                                  | Required | Effect                                                                              |
| -------------- | -------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `DATABASE_URL` | `postgresql://asobeast:asobeast@localhost:5432/asobeast` | Yes      | PostgreSQL connection string. Compose sets it from `POSTGRES_PASSWORD`              |
| `AUTH_SECRET`  | None                                                     | Yes      | Signs session cookies. At least 32 characters. Generate with `openssl rand -hex 32` |

## Core

| Variable          | Default     | Required | Effect                                                                          |
| ----------------- | ----------- | -------- | ------------------------------------------------------------------------------- |
| `REDIS_HOST`      | `localhost` | No       | Host holding the BullMQ queues                                                  |
| `REDIS_PORT`      | `6379`      | No       | Redis port                                                                      |
| `REDIS_DB`        | `0`         | No       | Redis database index for the queues. The end to end suite uses a separate index |
| `PORT`            | `4000`      | No       | Port the API listens on                                                         |
| `DEFAULT_COUNTRY` | `us`        | No       | Home storefront used when an import URL carries no country segment              |
| `LOG_LEVEL`       | `debug`     | No       | One of `error`, `warn`, `log`, `debug`, `verbose`                               |

## Scheduling

Every cron expression is evaluated in UTC. See [The daily pipeline and rate limits](/concepts/pipeline).

| Variable         | Default     | Required | Effect                                                                                         |
| ---------------- | ----------- | -------- | ---------------------------------------------------------------------------------------------- |
| `CRON_DAILY`     | `0 3 * * *` | No       | Starts the daily pipeline. Batched alerts flush after its processing completes, not on a clock |
| `CRON_SCORING`   | `0 4 * * 0` | No       | Recomputes traffic and difficulty weekly on Sunday                                             |
| `CRON_RETENTION` | `0 5 * * *` | No       | Prunes rows past their retention window                                                        |
| `CRON_AUDIT`     | `0 6 * * *` | No       | Writes the daily audit score snapshot                                                          |
| `CRON_DIGEST`    | `0 8 * * 1` | No       | Sends the weekly digest webhook on Monday                                                      |

## Collection rate limits

| Variable            | Default | Required | Effect                                                                                  |
| ------------------- | ------- | -------- | --------------------------------------------------------------------------------------- |
| `SCRAPE_ITUNES_RPM` | `15`    | No       | iTunes requests per minute. The App Store worker runs concurrency 1 behind this limiter |
| `SCRAPE_GPLAY_RPM`  | `10`    | No       | Google Play job starts per minute, not requests, because one job fans out to many       |

Raising either value risks the host IP address being throttled by the store. See [The daily pipeline and rate limits](/concepts/pipeline).

## Alerts

See [Send alerts](/guides/alerts).

| Variable                     | Default   | Required | Effect                                                                                                                            |
| ---------------------------- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `ALERT_DELIVERY`             | `batched` | No       | `batched` sends up to two scoped reports per channel after daily processing completes. `instant` sends one notification per event |
| `ALERT_RANK_DROP_THRESHOLD`  | `5`       | No       | Positions a primary app must move before a rank alert fires                                                                       |
| `ALERT_REVIEW_SCORE_MAX`     | `2`       | No       | Highest star rating treated as a negative review. Accepts 1 to 4                                                                  |
| `ALERT_ACTIONS_MIN_PRIORITY` | `high`    | No       | Lowest priority that fires `action.opened`. One of `critical`, `high`, `medium`, `low`                                            |
| `WEB_PUBLIC_URL`             | Empty     | No       | Public web origin. Used only to build deep links inside alert payloads. Unset leaves the link `null`                              |

## Email delivery

Email stays disabled until both `SMTP_HOST` and `SMTP_FROM` are set.

| Variable        | Default | Required | Effect                                                                         |
| --------------- | ------- | -------- | ------------------------------------------------------------------------------ |
| `SMTP_HOST`     | Empty   | No       | SMTP server host. Required to enable email                                     |
| `SMTP_PORT`     | `587`   | No       | Use `465` with `SMTP_SECURE=true`, otherwise 587 or 25                         |
| `SMTP_SECURE`   | `false` | No       | `true` wraps the connection in TLS from the start, which port 465 expects      |
| `SMTP_USER`     | Empty   | No       | Leave empty for an unauthenticated relay                                       |
| `SMTP_PASSWORD` | Empty   | No       | Paired with `SMTP_USER`                                                        |
| `SMTP_FROM`     | Empty   | No       | From address such as `asobeast <alerts@example.com>`. Required to enable email |

## Action Center

See [Work the Action Center](/guides/action-center).

| Variable                   | Default | Required | Effect                                                                                                                  |
| -------------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `ACTIONS_MAX_OPEN_PER_APP` | `20`    | No       | New actions one generation run may open per app, highest impact first. Existing open and snoozed actions always refresh |
| `ACTIONS_SNOOZE_MAX_DAYS`  | `90`    | No       | Furthest a snooze may be set into the future                                                                            |

## Data retention

`0` means keep forever. Pruning runs on `CRON_RETENTION`.

| Variable                        | Default | Required | Effect                                                                                 |
| ------------------------------- | ------- | -------- | -------------------------------------------------------------------------------------- |
| `RETENTION_RANKINGS_DAYS`       | `365`   | No       | Prunes keyword positions older than N days                                             |
| `RETENTION_SERP_DAYS`           | `90`    | No       | Prunes SERP entries older than N days                                                  |
| `RETENTION_SNAPSHOTS_DAYS`      | `180`   | No       | Prunes app snapshots older than N days. The newest snapshot per app is always kept     |
| `RETENTION_CATEGORY_RANKS_DAYS` | `365`   | No       | Prunes category ranks older than N days                                                |
| `RETENTION_CHANGE_EVENTS_DAYS`  | `0`     | No       | Prunes metadata change events older than N days                                        |
| `RETENTION_DELIVERIES_DAYS`     | `30`    | No       | Prunes alert delivery log rows older than N days                                       |
| `RETENTION_ALERT_EVENTS_DAYS`   | `30`    | No       | Prunes completed alert claims older than N days. Unfinished claims are always retained |
| `RETENTION_AUDIT_SCORES_DAYS`   | `0`     | No       | Prunes audit score history older than N days                                           |
| `RETENTION_ACTIONS_DAYS`        | `180`   | No       | Prunes closed action items only. Open and snoozed actions are never pruned by age      |

## Authentication

See [Authentication and accounts](/security/authentication).

| Variable                  | Default | Required | Effect                                                                                                                               |
| ------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `AUTH_SESSION_DAYS`       | `7`     | No       | Session cookie lifetime in days                                                                                                      |
| `AUTH_ALLOW_REGISTRATION` | `false` | No       | `true` keeps signups open. `false` closes registration once the first account exists. The first account always bootstraps as owner   |
| `AUTH_COOKIE_SECURE`      | `false` | No       | Marks the session cookie `Secure`. Must be `true` behind TLS on any hosted deployment                                                |
| `TRUST_PROXY`             | `false` | No       | `true` only behind a reverse proxy that sets a trustworthy `X-Forwarded-For`. Lets auth throttling key on the real client IP address |

## Entitlements

| Variable          | Default | Required | Effect                                                                                                 |
| ----------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------ |
| `BILLING_ENABLED` | `false` | No       | `true` starts every new account on a trial and answers `402` once it lapses, until the plan is premium |
| `TRIAL_DAYS`      | `7`     | No       | Trial length in days when `BILLING_ENABLED=true`                                                       |

## Optional AI

See [Enable the optional AI features](/guides/ai-features).

| Variable         | Default  | Required | Effect                                                                          |
| ---------------- | -------- | -------- | ------------------------------------------------------------------------------- |
| `OPENAI_API_KEY` | Empty    | No       | Empty disables the AI audit, metadata drafts and action explanations            |
| `AI_MODEL`       | `gpt-4o` | No       | Must support vision and structured outputs, because the audit reads screenshots |

## Admin surfaces

See [The queue dashboard and the OpenAPI surface](/security/admin-surfaces).

| Variable             | Default | Required | Effect                                                                          |
| -------------------- | ------- | -------- | ------------------------------------------------------------------------------- |
| `BULL_BOARD_ENABLED` | `true`  | No       | Serves the queue dashboard at `/admin/queues`. `false` removes it entirely      |
| `API_DOCS`           | `owner` | No       | Who may read `/docs`, `/docs-json` and `/docs-yaml`. `owner`, `public` or `off` |

## Compose only

These two live in the root `.env` and are read by `docker-compose.yml`, not by the API directly.

| Variable            | Default | Required | Effect                                                                    |
| ------------------- | ------- | -------- | ------------------------------------------------------------------------- |
| `POSTGRES_PASSWORD` | None    | Yes      | Sets the PostgreSQL role password and is interpolated into `DATABASE_URL` |
| `AUTH_SECRET`       | None    | Yes      | Passed through to the API container                                       |

## Retired variables

`BULL_BOARD_USER` and `BULL_BOARD_PASSWORD` are ignored. The queue dashboard now requires an owner session or a personal API token instead of basic authentication, and the API logs a warning at boot if either variable is still set. Remove them.

## Keeping this page correct

This page and the `.env.example` files change in the same commit. If a default here disagrees with `apps/api/.env.example`, the file is right and this page is a bug.
