Applications Guide — API Client Management
Tenxyte provides a built-in Application model to manage multiple API clients (such as Web apps, Mobile apps, testing scripts, or B2B integrations). Each application gets its own access_key and access_secret which are required to authenticate API requests.
Table of Contents
- Overview
- How It Works
- Configuration
- API Usage
- Create an Application
- List Applications
- Get Application Details
- Update an Application
- Regenerate Credentials
- Delete an Application
- Security Notes
- Python API
- Data Model
Overview
In modern systems, a backend usually serves multiple clients. Instead of using a single global API key or hardcoding credentials, Tenxyte allows you to generate distinct keys for each client.
For example, you could have:
- Web Frontend App
- iOS Mobile App
- Partner X Integration App
Tenxyte supports two authentication modes for applications:
| Mode | Headers | Use Case |
|---|---|---|
| Frontend (browser) | X-Access-Key + Origin header |
Web apps, SPAs |
| Backend (server-to-server) | X-Access-Key + X-Access-Secret |
Cron jobs, webhooks, admin scripts |
The X-Access-Secret must never be exposed in a browser environment.
How It Works
- Creation: An administrator creates an Application via the API (or Python code).
- Credentials Display: The system generates an
access_key(public) and anaccess_secret(private). The rawaccess_secretis returned only once and then securely hashed (bcrypt + base64) in the database. - Usage:
- Backend: Pass
X-Access-KeyandX-Access-Secretheaders. - Frontend: Pass only
X-Access-Key. The middleware validates the request'sOriginheader against the application'sallowed_originslist. - Revocation: If a secret leaks, administrators can regenerate credentials for that specific application or deactivate the application entirely.
Frontend (Key-Only) Mode
For browser-based clients, configure allowed_origins on the application:
# When creating the application
app, secret = Application.create_application(
name="Web Frontend",
allowed_origins=["https://app.example.com", "http://localhost:3000"],
)
The frontend only sends the public key:
If allowed_origins is empty, key-only mode is disabled and the secret is required.
Configuration
The default Application model can be customized. If you need to add fields (like rate limits, owner, etc.), you can extend AbstractApplication.
# Create a custom model
from tenxyte.models import AbstractApplication
from django.db import models
class CustomApplication(AbstractApplication):
owner = models.ForeignKey('users.User', on_delete=models.CASCADE)
api_rate_limit = models.IntegerField(default=1000)
class Meta(AbstractApplication.Meta):
db_table = 'custom_applications'
And update your settings.py:
API Usage
All endpoints are located under /api/v1/auth/applications/ and require appropriate RBAC permissions (applications.view, applications.create, applications.update, applications.delete, applications.regenerate) and a valid JWT.
Create an Application
Creates a new application and returns the secret.
POST /api/v1/auth/applications/
Authorization: Bearer <token>
{
"name": "Mobile iOS App",
"description": "Main iOS app for end-users",
"redirect_uris": ["myapp://callback", "https://app.example.com/auth"]
}
Response 201:
{
"message": "Application created successfully",
"application": {
"id": 1,
"name": "Mobile iOS App",
"description": "Main iOS app for end-users",
"access_key": "c4ca4238a0b923820dcc509a6f75849b...",
"is_active": true,
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z"
},
"credentials": {
"access_key": "c4ca4238a0b923820dcc509a6f75849b...",
"access_secret": "8b1a9953c4611296a827abf8c47804d7..."
},
"warning": "Save the access_secret now! It will never be shown again."
}
List Applications
Returns a paginated list of all applications.
Accepts query parameters such as ?search=mobile, ?is_active=true, ?ordering=name.
Get Application Details
Retrieves details of a standard application. The secret is never returned.
Update an Application
Updates the name or description of an application.
PUT /api/v1/auth/applications/1/
Authorization: Bearer <token>
{
"name": "Mobile iOS App v2",
"description": "Updated iOS app",
"is_active": true
}
Alternatively, use PATCH to quickly toggle the active status:
Regenerate Credentials
If a secret is compromised or lost, you can invalidate the old credentials and create new ones. This requires a specific explicit string confirmation ("REGENERATE").
POST /api/v1/auth/applications/1/regenerate/
Authorization: Bearer <token>
{
"confirmation": "REGENERATE"
}
Response 200:
{
"message": "Credentials regenerated successfully",
"application": { /* ... */ },
"credentials": {
"access_key": "new_key...",
"access_secret": "new_secret..."
},
"warning": "Save the access_secret now! It will never be shown again.",
"old_credentials_invalidated": true
}
Delete an Application
Permanently deletes the application and revokes its access completely.
Security Notes
- Hashing: Just like passwords, application secrets are securely hashed using
bcryptand stored in base64. They cannot be recovered by reading the database. - One-Time Display: The
access_secretis only returned once when thePOSTorregenerateendpoint is called. After that, it is inaccessible. - Deactivation: Before completely deleting an application, consider deactivating it (
PATCH is_active: false) to temporarily halt its access without losing its history and statistics.
Python API
You can programmatically interact with the Application model inside your Python code:
from tenxyte.models import get_application_model
Application = get_application_model()
# 1. Create Application
app, raw_secret = Application.create_application(
name="Test Script API",
description="For internal testing"
)
print(f"Key: {app.access_key}")
print(f"Secret: {raw_secret}")
# 2. Verify Secret
is_valid = app.verify_secret(raw_secret) # Returns True or False
# 3. Regenerate Credentials
new_credentials = app.regenerate_credentials()
print(new_credentials["access_key"])
print(new_credentials["access_secret"])
Data Model
Application (AbstractApplication)
├── id (Primary Key)
├── name (string)
├── description (text)
├── access_key (string, unique, indexed)
├── access_secret (string, hashed)
├── is_active (boolean, default: true)
├── allowed_origins (JSON array, default: [])
├── redirect_uris (JSON array, default: [])
├── created_at (datetime)
└── updated_at (datetime)
Note: When
allowed_originsis empty, key-only (frontend) auth is disabled and theX-Access-Secretis required. When populated, requests from those origins are accepted with onlyX-Access-Key.Note: When
redirect_urisis empty, all redirect URIs are permitted (backward-compatible). When populated, only exact matches are allowed during OAuth flows. See Security Guide for details.