API server config
Path: /admin-settings → API Server Config tab
Configure how the API server (TelAPI) instance set scales under load, and how inbound requests are throttled.
General
| Field | Required | Description |
|---|---|---|
| Enabled | Yes | Master toggle for the config. |
Auto-scaling
Same model as Server groups applied to API server instances.
| Field | Required | Default | Description |
|---|---|---|---|
| Scaling Enabled | Yes | false | Master toggle. |
| Min Instances | Yes | 1 | Never scales below. |
| Max Instances | Yes | 10 | Never scales above. |
| Scale Up Threshold | Yes | 0.7 | Utilisation (0 – 1) triggering scale-up. |
| Scale Down Threshold | Yes | 0.3 | Utilisation triggering scale-down. |
| Cooldown Seconds | Yes | 300 | Min wait between actions. |
| Scaling Provider | Yes | — | hetzner / aws / custom. |
| Scaling Config | No | — | Provider-specific JSON. |
Rate limiting
TelAPI applies IP-based server protection by route tier. Limits are stored in this config, cached in Redis, and reloaded automatically when you save (revision key voiceai:api-server-config:rev). /health and /metrics are always exempt.
| Field | Default | Description |
|---|---|---|
| Rate Limit Enabled | true | Master toggle for all tiers except health. |
| API Rate Limit Max | 600 | Max requests per client IP per window for authenticated API routes. |
| API Rate Limit Window (ms) | 60000 | Window for the API tier (60 000 = one minute). |
Auth routes (/api/v1/auth/*) use a fixed preset of 20 requests per minute per client IP until dedicated fields are added here.
When a tier limit is exceeded, TelAPI returns 429 Too Many Requests with error.code: RATE_LIMIT_EXCEEDED and optional details (max, after, ttlMs). See Errors.
TelAPI no longer reads RATE_LIMIT_MAX or RATE_LIMIT_WINDOW_MS. Remove them from the API service env bundle after upgrade. The former Per API Key toggle is also removed — server protection is always keyed by client IP + route tier.
This screen controls platform-wide server protection. Teams also have per-team daily quotas under Users and teams → API Access Configuration. A request can hit either limit independently.
API credential retry jail
The credential retry jail is configured through installation-level environment variables, separately from the request rate limits above. TelAPI counts failed authentication attempts per client IP in Redis across REST API keys and session WebSockets.
By default, the fifth failed authentication attempt within five minutes triggers a five-minute jail. The counting window starts with the first failure; later failures do not extend it. Successful authentication clears the retry counter. While jailed, the same IP remains blocked even with valid credentials until the jail expires. Protected HTTP requests receive 429 RATE_LIMIT_EXCEEDED with Retry-After. Authorization failures after successful authentication, such as a missing scope (403), do not count. Redis errors are logged and fail open.
| Variable | Default | Purpose |
|---|---|---|
API_CREDENTIAL_JAIL_ENABLED | true | Enable credential retry protection. |
API_CREDENTIAL_MAX_RETRIES | 5 | Failure count that triggers the jail. |
API_CREDENTIAL_RETRY_WINDOW_MS | 300000 | Counting window from the first failure, in milliseconds. |
API_CREDENTIAL_JAIL_MS | 300000 | Jail duration in milliseconds. |
Use the exact name API_CREDENTIAL_JAIL_MS. API_CREDENTIAL_JAIL_DURATION_MS is not read by TelAPI.
Configure an API installation
- Deploy API infrastructure configuration containing all five variables in both
/opt/services/api/vars.yamland thetelapi.environmentsection of/opt/services/api/docker-compose.yaml. The manifest controls which settings the loader exports; Compose controls which settings reach the container. Thecontainers: [telapi]manifest field does not automatically inject them. - Set installation overrides in AWS SSM Parameter Store under
/<NAMESPACE>/api/<VARIABLE_NAME>; for example,/VGW-DEV-GROUP-C2/api/API_CREDENTIAL_JAIL_MS. These non-sensitive settings use the normal SSM source and manifest defaults. If provisioning through Terraform, apply the updated service manifest to create the parameters. - From
/opt/services/api, run./init.sh --restart-only. This loads settings and recreates the containers using cached images. Ensure the deployed configuration source is updated too:init.shcan refresh files throughfetch-config, overwriting host-only edits. - Check the container environment:
docker exec voiceai-telapi env | sort | grep '^API_CREDENTIAL_'
For bootstrap-managed installations, source: local reads values from /opt/deployment/.env; the Compose mappings are still required. source: env is not a supported bootstrap source in fetch-env.sh. The environment index's “env” source label describes how the application reads a setting, not a vars.yaml source value. Do not put these settings in /opt/services/api/.env: init.sh removes that file before starting containers. SSM values can override bootstrap values for the same variable.
The original v0.9.17.0 application supports these settings, but its API infrastructure manifest and Compose file omitted all five mappings. Adding .env values or editing only vars.yaml does not resolve the omission; deploy both corrected infrastructure files. This configuration fix does not require rebuilding the application image.
When variables are absent, TelAPI uses its application defaults. Those defaults do not appear in docker exec ... env, so an empty environment check alone does not prove the jail is disabled.
Verify behavior
Use an isolated source IP and a protected REST API endpoint. Verify a valid request succeeds, fewer than five invalid attempts return 401, and a subsequent valid request resets the count. Then verify the fifth consecutive failure within the window returns 429 with Retry-After, a valid key from the jailed IP also returns 429, and valid requests succeed after expiry. Repeated authorization-only 403 responses must not create a jail.
Workflows
Configure rate limiting
Enable the config → toggle Enable Rate Limiting → set API max/window → save. Changes apply to running TelAPI instances without a container restart.
Enable auto-scaling
Enable the config → toggle Scaling on → set min/max/thresholds/cooldown/provider/config → save.