Documentation

Till lets you create scoped API keys for AI agents with activation, token, and dollar limits. Give agents disposable keys instead of your real ones. Whichever limit hits first kills the key.

New to Till? Follow the Quick Start to create your first scoped key in under a minute. No credit card needed.

Quick Start

  1. Create an account Sign up at till.ac. You'll get an admin key instantly. Save it - it's only shown once.
  2. Install the Python SDK pip install till-ac - or use the REST API directly.
  3. Create a scoped key Set limits and get a disposable key your agent can use as a drop-in replacement.
from till import TillClient client = TillClient(admin_key="till_admin_...") # Create a scoped key: 50 activations, 100K tokens, $5 budget key = client.create_key( provider="openai", upstream_key="sk-proj-...", max_activations=50, max_tokens=100_000, max_spend_cents=500, ) # Give to agent - drop-in OpenAI compatible from till.openai_compat import patched_openai ai = patched_openai(key.scoped_key) response = ai.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "Hello"}] )

Python SDK

The official Python SDK is the fastest way to work with Till.

pip install till-ac

The SDK provides:

Full SDK docs and source: pypi.org/project/till-ac

Scoped Keys

A scoped key is a disposable proxy key that wraps your real upstream API key with enforced limits. The format:

till_sk_<lookupKey>.<encryptedUpstreamKey> # Example (truncated): till_sk_mz90mM7bQ...VtkE.aGVsbG8gd29ybGQ...

When an agent makes a request with a scoped key, Till:

  1. Extracts the lookup key and finds the key record in the database
  2. Checks all three limits (activations, tokens, dollars)
  3. Decrypts the upstream key from the token (AES-256-GCM)
  4. Forwards the request to the upstream provider
  5. Tracks usage from the response and increments counters

Three Limits

Every scoped key can have up to three independent limits. Whichever hits first kills the key.

You can set any combination. A key with only an activation limit and no token/dollar limit works fine. So does a key with only a dollar limit.

Providers

Till supports 11 AI providers. All OpenAI-compatible providers use the same proxy path format:

Zero-Knowledge Architecture

Till's database stores zero upstream API keys. Here's how:

When you create a scoped key, your upstream API key is AES-256-GCM encrypted and embedded directly into the scoped token string. The database stores only:

If the Till database were breached, the attacker would find zero upstream keys. They're not there. The encrypted key material lives only in the scoped token you hold.

Authentication

All admin API requests require your admin key in the Authorization header:

# Admin operations (create keys, check status, etc.) Authorization: Bearer till_admin_your_key_here

The proxy endpoint uses the scoped key itself as authorization - your agent just uses it like a normal API key.

API Endpoints

Base URL: https://api.till.ac

Create a scoped key

POST /admin/keys { "provider": "openai", "upstream_key": "sk-proj-...", "max_activations": 50, "max_tokens": 100000, "max_spend_cents": 500, "expires_at": "2026-05-15T00:00:00Z", "metadata": {"name": "agent-task-42"} }

All fields except provider, upstream_key, and max_activations are optional. The optional expires_at field sets a time-based expiry (ISO 8601) — the key stops working after this time regardless of remaining limits.

List keys

GET /admin/keys GET /admin/keys?status=active GET /admin/keys?provider=openai&search=agent-name

Filter by status (active, exhausted, revoked, expired), provider, or search (searches key IDs and metadata).

Check key status

GET /admin/keys/:id

Update a key

PATCH /admin/keys/:id { "metadata": {"name": "renamed-agent"}, "ip_whitelist": ["10.0.0.0/8"], "max_activations": 200, "max_tokens": 50000, "max_spend_cents": 1000, "expires_at": "2026-12-31T23:59:59Z", "name": "renamed-agent" }

Update a key's limits, metadata, or IP allowlist without resetting counters. All fields are optional. New limits must not be below current usage. Set max_tokens, max_spend_cents, or expires_at to null to remove that ceiling.

Clone a key

POST /admin/keys/:id/clone { "upstream_key": "sk-proj-...", "max_activations": 100 }

Creates a fresh key with the same provider, limits, IP allowlist, and metadata as the source — but with reset counters. The upstream_key is required (Till doesn't store originals). Override any limit in the body. The new key's metadata includes a cloned_from field linking to the source.

Key usage

GET /admin/keys/:id/usage

Returns a structured usage breakdown with remaining and percent for activations, tokens, and spend.

Reactivate a key

POST /admin/keys/:id/reactivate { "max_activations": 100 }

Resets counters on an exhausted or expired key. The agent keeps its existing scoped key token. Optionally update limits in the body.

Revoke a key

DELETE /admin/keys/:id

Bulk revoke

POST /admin/keys/bulk-revoke { "ids": ["key-id-1", "key-id-2", "key-id-3"] }

Revoke up to 100 keys in a single call. Returns per-key status (revoked, not_found, or already_revoked). Useful for rotating upstream keys or decommissioning agent fleets.

Key stats

GET /admin/keys/stats

Returns aggregate counts (total, active, exhausted, revoked, expired), total activations/tokens/spend used, and a byProvider breakdown showing per-provider key counts.

Date range filtering

GET /admin/keys?created_after=2026-05-01T00:00:00Z&created_before=2026-05-07T00:00:00Z

Filter key listings by creation date using created_after and created_before query parameters (ISO 8601). Combine with other filters for time-based auditing.

Proxy Usage

To use a scoped key, keep the same request paths your SDK already uses and point the base URL to Till:

# Instead of: base_url = "https://api.openai.com/v1" api_key = "sk-proj-your-real-key" # Use: base_url = "https://api.till.ac/v1" api_key = "till_sk_your-scoped-key"

Common passthrough paths:

The proxy transparently forwards requests, tracks usage, and enforces limits. From the agent's perspective, only the base URL and API key change.

Response Headers

Every proxied response includes headers your agent can use to track its own key state:

Plans

All plans include all 11 providers, all three limit types, the dashboard, and the Python SDK.

FAQ

What counts as one activation?

One proxied HTTP request equals one activation. A 20-message conversation equals 20 activations (one per API call). A streaming response is still one activation.

Can I set only one type of limit?

Yes. Any combination works. Activation-only, dollar-only, all three, or any pair. Whichever limit you set is enforced. Unset limits are unlimited (within your plan's monthly cap).

How accurate is dollar tracking?

Till uses built-in pricing data for 80+ models. It reads token counts from upstream response headers and calculates cost immediately. Accuracy is within pennies of the actual provider bill.

What happens when a key is exhausted or expires?

Any request using an exhausted or expired key gets a clear error response with the reason (activation limit, token limit, dollar limit reached, or TTL expired). The agent can handle this gracefully. Use the clone endpoint to quickly create a replacement with the same config.

Can I use Till with frameworks like LangChain or LlamaIndex?

Yes. Any framework that lets you set a custom base_url and API key works with Till. The proxy is fully API-compatible with each upstream provider.