Getting Started
Authentication
User login and API key management
TL;DR
User login and API key management. URL: app.twig.so
Key Takeaways
- User Authentication
- API Authentication
- External API Keys
- SSO Integration
- OAuth for Data Connectors
- Security
User login and API key management.
User Authentication
Web Application Login
URL: app.twig.so
Methods:
- Email/Password: Standard authentication, JWT session token (7-day expiry)
- SSO: SAML 2.0 or OAuth 2.0 redirect to IdP
- OAuth: Google, Microsoft (redirect flow)
Flow:
- Enter credentials or click OAuth provider button
- Server validates, issues JWT
- JWT stored in httpOnly cookie
- All requests include cookie automatically
Session Details
- Storage: httpOnly secure cookie (name:
twig_session) - Expiry: 7 days (refreshed on each request)
- Refresh: Automatic (silent refresh 1 hour before expiry)
- Logout: DELETE
/api/auth/logout, cookie cleared
Observable behavior: Logged out after 7 days of inactivity. Login again to restore session.
API Authentication
API keys authenticate programmatic requests.
Generate API Key
- Log in to app.twig.so
- Settings → API Keys
- Click Generate New Key
- Fill form:
- Name: e.g., "Production API" (required)
- Scopes: Check boxes for Read, Write, Execute, Admin
- Environment: Live or Test
- Click Generate
Result: Key displayed once (format: twigsk_live_a1b2c3... or twigsk_test_x1y2z3...). Copy immediately.
Storage: Store in environment variable:
export TWIG_API_KEY="twigsk_live_a1b2c3..."
Use API Key
Include in Authorization header:
curl -X POST https://api.twig.so/v1/query \
-H "Authorization: Bearer $TWIG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "agent_abc123",
"query": "What is the pricing?",
"session_id": "sess_xyz789"
}'
Response (success):
{
"response": "Pricing starts at $99/month...",
"sources": [{"chunk_id": "chk_...", "similarity": 0.89}],
"latency_ms": 1432
}
Response (auth failure):
{
"error": "Invalid API key",
"status": 401
}
API Key Best Practices
Storage:
- ✅ Environment variables (
TWIG_API_KEY=...) - ✅ Secrets manager (AWS Secrets Manager, HashiCorp Vault)
- ❌ Hardcoded in source code
- ❌ Committed to git repos
- ❌ Shared in Slack/email
Key Management:
- Use separate keys for dev/staging/prod environments
- Rotate every 90 days (generate new, update apps, delete old)
- Delete unused keys immediately
- Monitor usage: Settings → API Keys → [Key Name] → Usage tab
Permissions:
- Grant minimum required scopes
- Production keys: Execute only (no Write/Admin)
- CI/CD keys: Read only for testing
API Key Scopes
| Scope | Permissions | Use Case |
|---|---|---|
| Read | GET /agents, /data-sources, /interactions | Analytics, monitoring dashboards |
| Write | POST/PUT/DELETE agents, data sources | Admin tools, setup automation |
| Execute | POST /query, /chat | Production apps, user-facing features |
| Admin | All endpoints including org settings | Full admin access, avoid for apps |
Observable behavior: API returns 403 Forbidden if scope insufficient:
{
"error": "Insufficient permissions",
"required_scope": "execute",
"current_scopes": ["read"]
}
External API Keys
Store third-party service credentials for custom model usage.
Supported Providers
- OpenAI: For bring-your-own-key (BYOK) usage, avoids Twig's shared pool
- Anthropic: For Claude models
- Custom LLM: Any OpenAI-compatible API endpoint
Add External Key
- Settings → External API Keys
- Click Add Key
- Fill form:
- Provider: Dropdown (OpenAI, Anthropic, Custom)
- API Key: Paste key
- Endpoint (Custom only): e.g.,
https://your-llm.com/v1
- Click Save
Security: Keys encrypted at rest (AES-256), never logged
Usage: Agent Configuration → Model → Select "Use my OpenAI key" (dropdown)
Observable behavior: Queries use your key instead of Twig's. Billing goes to your OpenAI/Anthropic account, not Twig.
SSO Integration
SAML/OAuth for enterprise user authentication.
Supported Protocols
- SAML 2.0: Okta, Azure AD, Google Workspace, OneLogin, Auth0
- OAuth 2.0: Google Workspace, Microsoft 365
- OIDC: OpenID Connect providers
Setup Process
Prerequisites: Enterprise plan, domain verified
Steps:
- Email support@twig.so with:
- IdP type (Okta, Azure AD, etc.)
- SSO metadata URL or XML file
- Attribute mapping (email → NameID)
- Twig configures SSO (1-2 business days)
- Test with 1-2 pilot users
- Enable for org: Settings → Authentication → Enforce SSO (toggle)
Post-setup:
- Users go to app.twig.so → "Sign in with SSO"
- Enter email → redirected to IdP → authenticated → redirected back
- Session managed as normal (7-day expiry)
Failure scenarios:
- Invalid SAML assertion → "Authentication failed" error page
- Email not in allowed domains → "Unauthorized domain" error
See SSO Setup Guide for IdP-specific instructions.
OAuth for Data Connectors
Third-party service authentication (Google Drive, Slack, etc.).
OAuth Flow
- Data → Add Data Source → Select connector (e.g., Google Drive)
- Click Connect
- Redirected to Google OAuth consent screen
- Grant permissions (read files)
- Redirected to app.twig.so
- Access token stored, data source status: "Connected"
Tokens:
- Access token: Short-lived (1 hour), used for API requests
- Refresh token: Long-lived (no expiry), auto-refreshes access token
- Storage: Encrypted in PostgreSQL
oauth_tokenstable
Revoke access: Data → [Source] → Settings → Disconnect (deletes tokens from Twig and revokes at provider)
Observable failure: If refresh token invalid (user revoked in Google), data source status: "Connection failed". Reconnect required.
Security
Token Security
Encryption:
- API keys: Hashed with bcrypt (cost factor: 12) before storage
- OAuth tokens: AES-256-GCM encryption at rest
- Session JWTs: HMAC-SHA256 signed, verified on each request
Transport:
- TLS 1.3 required (TLS 1.2 minimum)
- HTTPS only (HTTP redirects to HTTPS)
- HSTS header enabled (max-age: 31536000)
Verification: All API keys checked against PostgreSQL api_keys table on each request (cached in Redis for 5 minutes)
Rate Limiting
Limits by scope:
- Execute: 100 requests/minute
- Write: 10 requests/minute
- Read: 200 requests/minute
- Admin: 50 requests/minute
Implementation: Token bucket algorithm, enforced at API gateway (Cloudflare Workers)
Response when exceeded:
{
"error": "Rate limit exceeded",
"limit": 100,
"reset_at": "2024-01-15T10:35:00Z"
}
HTTP status: 429 Too Many Requests
Headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1610708100
Custom limits: Enterprise plan can request increases. Contact support with use case.
IP Allowlisting
Available on: Enterprise plan only
Setup: Settings → Security → IP Allowlist → Add range
Format: CIDR notation (e.g., 192.168.1.0/24, 10.0.0.5/32)
Enforcement: API gateway blocks requests from IPs not in list (returns 403 Forbidden)
Audit: All blocked attempts logged: Settings → Security → Access Logs
Troubleshooting
Error: Invalid API Key
Symptom: API returns 401 with:
{"error": "Invalid API key", "status": 401}
Diagnostic steps:
- Verify key format: Must start with
twigsk_live_ortwigsk_test_ - Check header:
Authorization: Bearer twigsk_live_...(note "Bearer" prefix) - Settings → API Keys → verify key not deleted
Common mistakes:
- Missing "Bearer" prefix in Authorization header
- Using test key (
twigsk_test_) against production API - Extra whitespace in key
Fix: Regenerate key if lost, update header format.
Error: Token Expired
Symptom: Web UI redirects to login after period of inactivity
Cause: Session JWT expired (7-day TTL)
Fix: Log in again. Session auto-refreshes if you use UI within 7 days.
API users: This doesn't apply to API keys (no expiry).
Error: Insufficient Permissions
Symptom: API returns 403 with:
{
"error": "Insufficient permissions",
"required_scope": "execute",
"current_scopes": ["read"]
}
Diagnostic steps:
- Settings → API Keys → [Your Key] → check Scopes section
- Verify required scope in error message
- Check if key belongs to correct organization
Fix:
- Delete key, generate new one with correct scopes
- Or: Contact org admin to regenerate with proper scopes
Error: Rate Limit Exceeded
Symptom: 429 response after burst of requests
Diagnostic steps:
- Check response headers:
X-RateLimit-Limit: Your limit (e.g., 100)X-RateLimit-Reset: Unix timestamp when reset occurs
- Calculate wait time:
reset_timestamp - current_timestamp
Fix:
- Implement exponential backoff in your client
- Reduce request frequency
- Enterprise: Request limit increase from support
SSO Login Fails
Symptom: Redirected to error page after IdP authentication
Diagnostic steps:
- Check error message (e.g., "Invalid SAML assertion", "Email domain not allowed")
- Settings → Authentication → SSO Config → verify IdP metadata URL still valid
- Test SAML response with browser dev tools (Network tab)
Common issues:
- Email attribute not mapped correctly (NameID must contain email)
- SAML certificate expired at IdP
- User's email domain not in allowed list
Fix: Contact support@twig.so with SAML response XML for diagnosis.
Next Steps
Quick Start Guide - Create your first agent
REST API Reference - API endpoint documentation
Security Best Practices - Secure your deployment
Agent Instructions: Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.
Perform an HTTP GET request on the current page URL with the ask query parameter:
GET /dev/getting-started/authentication.md?ask=<question>
The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.
Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
Related Pages
Last updated January 26, 2026


