Learn how to set up TensorZero API keys to authenticate your inference requests and manage access control for your workflows.
Configure your gateway to require authentication
[gateway]auth.enabled =true/status and/health will require authentication.Deploy TensorZero and Postgres
Example: Docker Compose
# This is a simplified example for learning purposes. Do not use this in production.# For production-ready deployments, see: https://www.tensorzero.com/docs/deployment/tensorzero-gatewayservices: clickhouse: image:clickhouse:lts environment: CLICKHOUSE_USER:chuser CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:1 CLICKHOUSE_PASSWORD:chpassword ports: -"8123:8123" # HTTP port -"9000:9000" # Native port volumes: -clickhouse-data:/var/lib/clickhouse ulimits: nofile: soft:262144 hard:262144 healthcheck: test:wget --spider --tries 1 http://chuser:chpassword@clickhouse:8123/ping start_period:30s start_interval:1s timeout:1s postgres: image:postgres:14-alpine environment: POSTGRES_DB:tensorzero POSTGRES_USER:postgres POSTGRES_PASSWORD:postgres ports: -"5432:5432" volumes: -postgres-data:/var/lib/postgresql/data healthcheck: test:pg_isready -U postgres start_period:30s start_interval:1s timeout:1s gateway: image:tensorzero/gateway volumes: -./config:/app/config:ro command:--config-file /app/config/tensorzero.toml environment: TENSORZERO_CLICKHOUSE_URL:http://chuser:chpassword@clickhouse:8123/tensorzero TENSORZERO_POSTGRES_URL:postgres://postgres:postgres@postgres:5432/tensorzero OPENAI_API_KEY:${OPENAI_API_KEY:?Environment variable OPENAI_API_KEY must be set.} ports: -"3000:3000" extra_hosts: -"host.docker.internal:host-gateway" healthcheck: test:wget --spider --tries 1 http://localhost:3000/status start_period:30s start_interval:1s timeout:1s depends_on: clickhouse: condition:service_healthy postgres: condition:service_healthy ui: image:tensorzero/ui volumes: -./config:/app/config:ro environment: OPENAI_API_KEY:${OPENAI_API_KEY:?Environment variable OPENAI_API_KEY must be set.} TENSORZERO_CLICKHOUSE_URL:http://chuser:chpassword@clickhouse:8123/tensorzero TENSORZERO_POSTGRES_URL:postgres://postgres:postgres@postgres:5432/tensorzero TENSORZERO_GATEWAY_URL:http://gateway:3000 ports: -"4000:4000" depends_on: clickhouse: condition:service_healthy gateway: condition:service_healthyvolumes: postgres-data: clickhouse-data:Create a TensorZero API key
http://localhost:4000/api-keys to create a key.Alternatively, you can create API keys programmatically in the CLI using the gateway binary with the--create-api-key flag.For example:docker compose run --rm gateway --create-api-keyTENSORZERO_API_KEY environment variable.Make an authenticated inference request
api_key parameter in your TensorZero client:import osfrom tensorzeroimport TensorZeroGatewayt0= TensorZeroGateway.build_http( api_key=os.environ["TENSORZERO_API_KEY"], gateway_url="http://localhost:3000",)response= t0.inference( model_name="openai::gpt-5-mini", input={ "messages": [ { "role":"user", "content":"Tell me a fun fact.", } ] },)print(response)TENSORZERO_API_KEY environment variable if you don’t setapi_key.api_key parameter in your OpenAI client:import osfrom openaiimport OpenAIclient= OpenAI( api_key=os.environ["TENSORZERO_API_KEY"], base_url="http://localhost:3000/openai/v1",)response= client.chat.completions.create( model="tensorzero::model_name::openai::gpt-5-mini", messages=[ { "role":"user", "content":"Tell me a fun fact.", } ],)print(response)apiKey parameter in your OpenAI client:import OpenAI from "openai";const client = new OpenAI({ apiKey: process.env.TENSORZERO_API_KEY, baseURL: "http://localhost:3000/openai/v1",});const response = await client.chat.completions.create({ model: "tensorzero::model_name::openai::gpt-5-mini", messages: [ { role: "user", content: "Tell me a fun fact.", }, ],});Authorization HTTP header toBearer <API_KEY>:curl -X POST http://localhost:3000/openai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${TENSORZERO_API_KEY}" \ -d '{ "model": "tensorzero::model_name::openai::gpt-5-mini", "messages": [ { "role": "user", "content": "Tell me a fun fact." } ] }'Manage API keys in the TensorZero UI
http://localhost:4000/api-keys to manage your keys.[gateway.auth.cache]enabled =true # booleanttl_ms =60_000 # one minuteapi_key_public_id scope in your rate limiting rules.This allows you to enforce different usage limits for different API keys, which is useful for implementing tiered access or preventing individual keys from consuming too many resources.sk-t0-xxxxxxxxxxxx-yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyThexxxxxxxxxxxx portion is the 12-character public ID that you can use in rate limiting rules.The remaining portion of the key is secret and should be kept secure.# Each API key can make up to 100 model inferences per hour[[rate_limiting.rules]]priority =0model_inferences_per_hour =100scope = [ {api_key_public_id ="tensorzero::each" }]# But override the limit for a specific API key[[rate_limiting.rules]]priority =1model_inferences_per_hour =1000scope = [ {api_key_public_id ="xxxxxxxxxxxx" }]