SDK Authentication
Learn how to securely authenticate your applications with AxonFlow using OAuth2-style credentials and best practices for production deployments.
Installation
Install the AxonFlow SDK for your language to get started:
| Language | Install Command | Package |
|---|---|---|
| TypeScript | npm install @axonflow/sdk | @axonflow/sdk |
| Python | pip install axonflow | axonflow |
| Go | go get github.com/getaxonflow/axonflow-sdk-go/v8 | axonflow-sdk-go |
| Java | Add com.getaxonflow:axonflow-sdk:8.5.0 to pom.xml | Maven Central |
For language-specific setup details, see Go SDK, Python SDK, TypeScript SDK, or Java SDK.
Overview
AxonFlow uses OAuth2-style Basic authentication for all deployments. Each organization uses a client ID (required) and client secret (optional for community mode) to authenticate API requests.
Authentication Header: Authorization: Basic base64(clientId:clientSecret)
Note: The client ID is recommended even for community/self-hosted deployments for request identification, metrics attribution, and audit logging. The client secret is only required for enterprise deployments.
Automatic headers the SDK sets for you
In addition to Authorization, the AxonFlow SDKs (TypeScript / Python / Go / Java) automatically set two headers on every governed request — you don't configure these:
| Header | Value | Purpose |
|---|---|---|
User-Agent | axonflow-sdk-<lang>/<version> | Standard SDK identification used for compatibility checks against the platform's /health plugin-compatibility manifest. |
X-Axonflow-Client | sdk-<lang>/<version> (e.g. sdk-typescript/7.8.0) | Identifies which SDK is calling the agent so the platform can validate license-token scope (sdk vs plugin vs full) per the License Matrix. The value is sourced from the bundled SDK version constant — the consumer cannot spoof its own client identity through config. |
The X-Axonflow-Client header is set automatically as of SDK v7.0.1 / v7.8.0 across all four SDKs. It only matters when you also send a Pro-tier X-License-Token (Community SaaS endpoints only); the agent validates the token's aud.scope matches the derived sdk scope before applying Pro-tier entitlements. For the rest of the auth model below, you can ignore it.
Getting Your Credentials
For AWS Marketplace Deployments (In-VPC)
After deploying AxonFlow via AWS CloudFormation:
- Credentials are automatically generated during deployment
- Find them in AWS Secrets Manager at:
axonflow/customers/{your-org-id}/credentials - Or check CloudFormation stack outputs for
ClientIDandClientSecret
Retrieve via AWS CLI:
aws secretsmanager get-secret-value \
--secret-id axonflow/customers/your-org-id/credentials \
--region eu-central-1 \
--query 'SecretString' \
--output text | jq .
For Direct Purchases
Contact AxonFlow sales to receive your organization's credentials:
- Email: [email protected]
- Subject: "Credentials Request - [Your Organization]"
- Response Time: 1 business day
You'll receive credentials via secure channel (encrypted email or AWS Secrets Manager).
Using Credentials
Set AXONFLOW_TRY=1 to auto-connect to the free trial server. Requires AXONFLOW_CLIENT_ID and AXONFLOW_CLIENT_SECRET from registration. No Docker or self-hosting needed.
Method 1: Environment Variables (Recommended)
TypeScript/JavaScript:
import { AxonFlow } from '@axonflow/sdk';
const axonflow = new AxonFlow({
clientId: process.env.AXONFLOW_CLIENT_ID,
clientSecret: process.env.AXONFLOW_CLIENT_SECRET, // Optional for community mode
endpoint: process.env.AXONFLOW_ENDPOINT
});
Go:
import (
"os"
"github.com/getaxonflow/axonflow-sdk-go/v8"
)
client := axonflow.NewClient(axonflow.AxonFlowConfig{
ClientID: os.Getenv("AXONFLOW_CLIENT_ID"),
ClientSecret: os.Getenv("AXONFLOW_CLIENT_SECRET"), // Optional for community mode
Endpoint: os.Getenv("AXONFLOW_ENDPOINT"),
})
Java:
import com.getaxonflow.sdk.AxonFlow;
import com.getaxonflow.sdk.AxonFlowConfig;
AxonFlowConfig config = AxonFlowConfig.builder()
.clientId(System.getenv("AXONFLOW_CLIENT_ID"))
.clientSecret(System.getenv("AXONFLOW_CLIENT_SECRET")) // Optional for community mode
.endpoint(System.getenv("AXONFLOW_ENDPOINT"))
.build();
AxonFlow client = AxonFlow.create(config);
Python:
import os
from axonflow import AxonFlow
client = AxonFlow(
client_id=os.getenv("AXONFLOW_CLIENT_ID"),
client_secret=os.getenv("AXONFLOW_CLIENT_SECRET"), # Optional for community mode
endpoint=os.getenv("AXONFLOW_ENDPOINT")
)
Environment file (.env):
# OAuth2 Credentials (Current Method)
AXONFLOW_CLIENT_ID=your-org-id
AXONFLOW_CLIENT_SECRET=your-secret-key
AXONFLOW_ENDPOINT=https://YOUR_VPC_IP:8443
# Or for the public community SaaS at try.getaxonflow.com
AXONFLOW_CLIENT_ID=your-org-id
AXONFLOW_CLIENT_SECRET=your-secret-key
AXONFLOW_ENDPOINT=https://try.getaxonflow.com
Method 2: AWS Secrets Manager (Production Recommended)
For production In-VPC deployments, store credentials in AWS Secrets Manager:
TypeScript (AWS SDK v3):
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
import { AxonFlow } from '@axonflow/sdk';
async function getAxonFlowClient() {
const secretsManager = new SecretsManagerClient({ region: 'eu-central-1' });
const response = await secretsManager.send(
new GetSecretValueCommand({
SecretId: 'axonflow/customers/your-org-id/credentials'
})
);
const credentials = JSON.parse(response.SecretString!);
return new AxonFlow({
clientId: credentials.client_id,
clientSecret: credentials.client_secret,
endpoint: 'https://YOUR_VPC_IP:8443'
});
}
const axonflow = await getAxonFlowClient();
Go:
import (
"encoding/json"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/getaxonflow/axonflow-sdk-go/v8"
)
type Credentials struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
}
func getAxonFlowClient() (*axonflow.AxonFlowClient, error) {
sess := session.Must(session.NewSession())
svc := secretsmanager.New(sess, aws.NewConfig().WithRegion("eu-central-1"))
result, err := svc.GetSecretValue(&secretsmanager.GetSecretValueInput{
SecretId: aws.String("axonflow/customers/your-org-id/credentials"),
})
if err != nil {
return nil, err
}
var creds Credentials
if err := json.Unmarshal([]byte(*result.SecretString), &creds); err != nil {
return nil, err
}
client := axonflow.NewClient(axonflow.AxonFlowConfig{
ClientID: creds.ClientID,
ClientSecret: creds.ClientSecret,
Endpoint: "https://YOUR_VPC_IP:8443",
})
return client, nil
}
Credential Configuration Reference
| Parameter | Environment Variable | Type | Required | Description |
|---|---|---|---|---|
clientId / ClientID / client_id | AXONFLOW_CLIENT_ID | string | Yes | Your API credential identifier. In v9 terminology, this is client_id — the credential/app identity inside your customer organization. Used for request attribution, metrics, and audit logging. |
clientSecret / ClientSecret / client_secret | AXONFLOW_CLIENT_SECRET | string | Enterprise only | Authentication secret. Optional for community/self-hosted mode. Required for enterprise and SaaS deployments. |
endpoint / Endpoint | AXONFLOW_ENDPOINT | string | Yes | AxonFlow Agent URL. For the public community SaaS: https://try.getaxonflow.com. For In-VPC: https://YOUR_VPC_IP:8443. |
tenant / Tenant | AXONFLOW_TENANT | string | Legacy only | Deprecated compatibility field. Prefer customer-specific clientId / clientSecret pairs or service-side credential lookup instead of new tenant-based examples. See v7 → v8 Migration Guide for the conceptual mapping. |
org_id= your customer organization (Row-Level-Security boundary in v9).client_id= the API credential/app identity inside that org. This is theclientIdyou set in the SDK.- These were both called
tenant_idin pre-v9 docs. The SDK already usesclientIdcorrectly; the platform derives bothorg_idandclient_idfrom the authenticated request. See Auth and Header Matrix — Identity Primer.
Security Best Practices
1. Never Hardcode Credentials
Bad:
const axonflow = new AxonFlow({
clientId: 'my-org-id', // Hardcoded!
clientSecret: 'secret-abc123' // Hardcoded!
});
Good:
const axonflow = new AxonFlow({
clientId: process.env.AXONFLOW_CLIENT_ID,
clientSecret: process.env.AXONFLOW_CLIENT_SECRET
});
2. Use Environment-Specific Credentials
Separate credentials for development, staging, and production:
# .env.development
AXONFLOW_CLIENT_ID=dev-org
AXONFLOW_CLIENT_SECRET=dev-secret
# .env.production
AXONFLOW_CLIENT_ID=prod-org
AXONFLOW_CLIENT_SECRET=prod-secret
3. Rotate Credentials Regularly
For production environments, rotate credentials every 90 days:
- Generate new credentials in AxonFlow dashboard
- Update environment variables/Secrets Manager
- Deploy updated configuration
- Revoke old credentials after 24 hours
4. Restrict Credential Permissions
In multi-tenant environments, use least-privilege credentials:
// Healthcare tenant only has access to healthcare policies
const healthcareAxonFlow = new AxonFlow({
clientId: process.env.HEALTHCARE_CLIENT_ID,
clientSecret: process.env.HEALTHCARE_CLIENT_SECRET,
});
// E-commerce tenant has separate access
const ecommerceAxonFlow = new AxonFlow({
clientId: process.env.ECOMMERCE_CLIENT_ID,
clientSecret: process.env.ECOMMERCE_CLIENT_SECRET,
});
5. Never Expose Credentials Client-Side
Never do this in React/Vue/Angular:
// THIS IS INSECURE - Don't put credentials in frontend code!
const axonflow = new AxonFlow({
clientId: 'my-org', // Exposed in browser!
clientSecret: 'secret-abc123' // Exposed in browser!
});
Instead, use a backend proxy:
// Frontend - calls your backend
const response = await fetch('/api/ai-query', {
method: 'POST',
body: JSON.stringify({ prompt })
});
// Backend API route - has credentials
import { AxonFlow } from '@axonflow/sdk';
const axonflow = new AxonFlow({
clientId: process.env.AXONFLOW_CLIENT_ID, // Safe - server-side only
clientSecret: process.env.AXONFLOW_CLIENT_SECRET,
endpoint: process.env.AXONFLOW_ENDPOINT
});
export default async function handler(req, res) {
const { prompt, userToken } = req.body;
// Use Proxy Mode for simple governance
const result = await axonflow.proxyLLMCall({
userToken: userToken || 'anonymous',
query: prompt,
requestType: 'chat'
});
res.json(result);
}
HTTP API Authentication
For direct HTTP API calls without an SDK, use Basic authentication:
# Create the Base64-encoded credentials
AUTH=$(echo -n 'your-client-id:your-client-secret' | base64)
# Make authenticated request
curl -X POST https://your-endpoint.com/api/v1/request \
-H "Authorization: Basic $AUTH" \
-H "Content-Type: application/json" \
-d '{
"query": "What is 2+2?",
"request_type": "chat"
}'
For community mode (no client secret):
# Use just the client ID
AUTH=$(echo -n 'your-client-id:' | base64)
curl -X POST https://your-endpoint.com/api/v1/request \
-H "Authorization: Basic $AUTH" \
-H "Content-Type: application/json" \
-d '{...}'
Multi-Tenant Authentication
For SaaS applications serving multiple tenants:
Tenant Isolation
import { AxonFlow } from '@axonflow/sdk';
// Initialize once per tenant
function getAxonFlowForTenant(tenantId: string) {
const tenant = resolveTenantCredentials(tenantId);
return new AxonFlow({
clientId: tenant.clientId,
clientSecret: tenant.clientSecret,
endpoint: tenant.endpoint
});
}
// Usage
const tenant1Client = getAxonFlowForTenant('healthcare-corp');
const tenant2Client = getAxonFlowForTenant('ecommerce-inc');
// Each client only sees their own policies and audit logs
Per-Tenant Credentials
For stricter isolation, use separate credentials per tenant. The column names in your application database are entirely yours — what matters at the AxonFlow boundary is the clientId you pass in:
// Your application's database schema (your column names, your choice)
{
your_tenant_key: 'healthcare-corp', // your application's tenant primary key
axonflow_client_id: 'healthcare-client', // maps to AxonFlow client_id (Basic Auth username)
axonflow_client_secret: 'healthcare-secret',
created_at: '2025-10-01'
}
// Retrieve from database
function getAxonFlowForTenant(yourTenantKey: string) {
const tenant = db.tenants.findOne({ your_tenant_key: yourTenantKey });
return new AxonFlow({
clientId: tenant.axonflow_client_id,
clientSecret: tenant.axonflow_client_secret,
endpoint: tenant.axonflow_endpoint
});
}
Common Authentication Issues
Issue 1: 401 Unauthorized
Cause: Invalid or missing credentials
Solution:
// Check credentials are set
console.log('Client ID:', process.env.AXONFLOW_CLIENT_ID?.substring(0, 10) + '...');
// Verify credentials are not empty
if (!process.env.AXONFLOW_CLIENT_ID) {
throw new Error('Missing AXONFLOW_CLIENT_ID');
}
Issue 2: 403 Forbidden
Cause: Credentials valid but lacks permissions
Solution:
- Check tenant ID matches your credentials
- Verify license tier supports requested features
- Contact support to upgrade tier if needed
Issue 3: Connection Refused
Cause: Wrong endpoint URL
Solution:
For SaaS Mode:
const axonflow = new AxonFlow({
endpoint: 'https://try.getaxonflow.com' // Public community SaaS
});
For In-VPC Mode:
const axonflow = new AxonFlow({
endpoint: 'https://YOUR_VPC_IP:8443' // VPC private endpoint (replace YOUR_VPC_IP)
});
Testing Authentication
Quick Test (cURL)
# Test against the public community SaaS
curl -X POST https://try.getaxonflow.com/api/v1/request \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n 'your-client-id:your-client-secret' | base64)" \
-d '{
"query": "What is 2+2?",
"request_type": "chat"
}'
# Expected: 200 OK with JSON response
Integration Test
TypeScript:
import { AxonFlow } from '@axonflow/sdk';
async function testAuthentication() {
const axonflow = new AxonFlow({
clientId: process.env.AXONFLOW_CLIENT_ID,
clientSecret: process.env.AXONFLOW_CLIENT_SECRET,
endpoint: process.env.AXONFLOW_ENDPOINT
});
try {
// Simple health check
const health = await axonflow.healthCheck();
console.log('Authentication successful');
return true;
} catch (error) {
console.error('Authentication failed:', error.message);
return false;
}
}
testAuthentication();
Go:
func testAuthentication() error {
client := axonflow.NewClient(axonflow.AxonFlowConfig{
Endpoint: os.Getenv("AXONFLOW_ENDPOINT"),
ClientID: os.Getenv("AXONFLOW_CLIENT_ID"),
ClientSecret: os.Getenv("AXONFLOW_CLIENT_SECRET"),
})
err := client.HealthCheck()
if err != nil {
return fmt.Errorf("authentication failed: %v", err)
}
fmt.Println("Authentication successful")
return nil
}
Legacy Authentication (Deprecated)
Warning: The
licenseKey/LicenseKeyparameter andX-License-Keyheader are deprecated as of November 2025 and will be removed after June 2026. Migrate to OAuth2 credentials (clientId/clientSecret) as shown in the examples above.
Migration summary:
- Replace
AXONFLOW_LICENSE_KEYenv var withAXONFLOW_CLIENT_IDandAXONFLOW_CLIENT_SECRET - Update SDK initialization to use
clientId/clientSecret(orClientID/ClientSecretin Go) instead oflicenseKey/LicenseKey - Contact [email protected] with subject "OAuth2 Migration Request" to obtain your new credentials
Quick reference -- old vs new:
# OLD (remove)
AXONFLOW_LICENSE_KEY=AXON-ENT-xxx-yyy
# NEW (add)
AXONFLOW_CLIENT_ID=your-org-id
AXONFLOW_CLIENT_SECRET=your-secret-key
For detailed migration assistance, contact [email protected] or join #oauth2-migration on Slack.
Next Steps
- Review TypeScript SDK Guide for code examples
- Review Go SDK Guide for Go integration
- Learn about AWS Marketplace Deployment for In-VPC setup
- Read Security Best Practices for production security
Support
Having authentication issues?
- Email: [email protected]
- Slack: Join our community
- Docs: https://docs.getaxonflow.com
Include in your support request:
- SDK version (TypeScript/Go/Java/Python)
- Deployment mode (SaaS or In-VPC)
- Error message and stack trace
- Client ID (first 10 characters only, never share secret)
