Overview
All Trix API requests require authentication. We use API keys for simplicity and security. Keys are scoped to your organization and can be configured with specific permissions.
Just add your API key to the client — no OAuth flows, no token refresh logic, no complexity.
Keys are hashed and encrypted. You can set IP allowlists, rate limits, and expiration dates.
Getting Your API Key
Generate API keys using the Trix CLI:
# Log in to your Trix account
trix auth login
# Create a new API key
trix keys create --name "my-app"
# Output:
# ✓ API key created: gdb_abc123...
#
# Save this key now — it won't be shown again.Store your key securely. API keys are only displayed once when created. If you lose a key, you'll need to generate a new one.
Using Your API Key
Pass your API key when initializing the Trix client:
import { Trix } from '@trixdb/client';
// Initialize with your API key
const trix = new Trix({
apiKey: process.env.TRIX_API_KEY
});
// All subsequent calls are authenticated
await trix.memories.create({ content: 'User prefers dark mode' });REST API Authentication
When using the REST API directly, include your API key in the Authorization header:
const response = await fetch('https://api.trixdb.com/v1/memories', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.TRIX_API_KEY}`,
'Content-Type': 'application/json',
'X-Trix-Session': 'user_123'
},
body: JSON.stringify({
content: 'User prefers dark mode'
})
});API Key Types
Trix provides different key types for different environments:
Planned feature. Today every key is prefixed gdb_ with no environment distinction. Environment-specific prefixes (gdb_prod_, gdb_test_, gdb_ci_) and auto-cleared CI keys are planned — see ADR-142.
| Type | Prefix | Purpose | Data Isolation |
|---|---|---|---|
| Production | gdb_prod_ | Live applications with real user data | Full data persistence |
| Test | gdb_test_ | Development and testing | Isolated, can be cleared |
| CI/CD | gdb_ci_ | Automated testing pipelines | Auto-cleared after 24h |
Best practice: Use test keys during development to avoid polluting production data. Data created with test keys is completely isolated.
Key Scopes & Permissions
API keys can be scoped to limit their permissions. This follows the principle of least privilege:
Planned feature. Scope enforcement is not yet implemented; today trix keys create accepts --admin (full access) only. The scope model below is the target design — see ADR-142.
| Scope | Permissions | Use Case |
|---|---|---|
memories:write | Create and update memories | Backend services that store user context |
memories:read | Recall and list memories | Read-only analytics or reporting |
memories:delete | Delete memories | Admin tools, GDPR compliance |
session:manage | Create, list, delete sessions | User management systems |
* | Full access | Development, admin dashboards |
Specify scopes when creating a key with the CLI:
# Planned — scopes are not yet enforced. Today you can create keys with:
trix keys create --name "production-backend" --expires 720h
# Output:
# Key created: gdb_abc123...
# Expires in: 30 days
# When ADR-142 ships, the syntax will be:
# trix keys create --name "production-backend" \
# --scopes memories:write,memories:read \
# --expires 30dSessions
Sessions isolate memories between users. Every API request should include a session identifier.
// Use spaces to isolate memories between users
const trix = new Trix({ apiKey: process.env.TRIX_API_KEY });
await trix.memories.create({
content: 'Prefers dark mode',
spaceId: 'user_123'
});
await trix.memories.create({
content: 'Prefers light mode',
spaceId: 'user_456'
});
// Memories are isolated — user_123 can't see user_456's dataTip: Use your existing user IDs as session identifiers. This makes it easy to query a user's memories and ensures proper isolation.
Key Rotation
Rotate your API keys periodically to maintain security:
- Create a new key with the CLI using the same permissions
- Update your application to use the new key
- Deploy the change to all environments
- Verify the new key is working correctly
- Revoke the old key using
trix keys delete
# List all active keys
trix keys list
# Delete an old key by its ID (not the raw key)
trix keys delete <key-id>
# Output:
# Key deleted: <key-id>Zero-downtime rotation: Always deploy the new key before revoking the old one. This prevents service interruptions.
Security Best Practices
Follow these practices to keep your API keys secure:
Use Environment Variables
Never hardcode API keys. Store them in .env files or your platform's secret manager.
Separate Environments
Use different keys for development, staging, and production. Never share keys across environments.
Set Expiration Dates
Configure keys to expire automatically. This limits exposure if a key is compromised.
IP Allowlisting (planned)
Restrict production keys to known IP addresses. Per-key allowlists are planned — see ADR-142.
Monitor Usage
Set up alerts for unusual API patterns. Investigate spikes in usage or unexpected sessions.
Least Privilege
Only grant the scopes each key needs. A backend that only reads doesn't need write access.
Authentication Errors
All Trix API errors follow the Fastify-sensible shape { statusCode, error, message }. Authentication failures return HTTP 401 with error: "UnauthorizedError" and a human-readable message. The SDKs wrap these in typed exception classes (AuthenticationError, PermissionError, RateLimitError, …) — switch on the class, not on a string code.
| HTTP Status | SDK Exception | Typical message | Solution |
|---|---|---|---|
| 401 | AuthenticationError | "Missing Authorization header" / "Invalid Authorization header format. Use: Bearer <token>" / "Invalid API key" / "API key is inactive" | Check header format and key validity; regenerate if needed |
| 403 | PermissionError | "Forbidden" / resource-specific permission denials | Use a different actor or verify ownership |
| 429 | RateLimitError | "Rate limit exceeded" | Honor the Retry-After header; upgrade plan if sustained |
Planned: per-key scope enforcement and IP allowlisting (ADR-142) will add new 403 messages. Today there is no scope or per-key IP check.
import { Trix, AuthenticationError, PermissionError, RateLimitError } from '@trixdb/client';
const trix = new Trix({ apiKey: process.env.TRIX_API_KEY });
try {
await trix.memories.create({ content: 'User prefers dark mode' });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Authentication failed:', error.message);
// Alert ops team, check configuration
} else if (error instanceof PermissionError) {
console.error('Permission denied:', error.message);
} else if (error instanceof RateLimitError) {
console.error('Rate limited, retrying in', error.retryAfter, 's');
await new Promise(r => setTimeout(r, (error.retryAfter ?? 30) * 1000));
// Retry the request
}
}Next Steps
Now that you understand authentication, explore: