Paramtune docs
API documentation.
All API endpoints return JSON responses. CORS is controlled via the CORS_ORIGIN environment variable and middleware.
Base URL
- Development:
http://localhost:3000/api - Production:
https://yourdomain.com/api
Authentication
People use the dashboard session cookie, which allows reads and writes.
Services and CI jobs use a read-only API token, created under Dashboard → API tokens:
curl -H "Authorization: Bearer ptk_..." https://yourdomain.com/api/mobile/1.1.0- Tokens work on
GET/HEADof/api/schemas,/api/{platform},/api/{platform}/versionsand/api/{platform}/{version}. Writes with a token return403; dashboard endpoints under/api/_ui/v1don't accept tokens. - A token reads either every platform or a chosen list. Out-of-scope platforms return
404and are omitted from/api/schemas. - A schema's resolved
outputincludes everything it inherits through@extends, so a scoped token can read a schema only when its scope covers every platform merged into that output, transitively. Otherwise the read returns403. Each save records these platforms assources; schemas with@extendssaved before this was recorded are readable by scoped tokens only after their next save. - The plaintext is shown once at creation. Paramtune stores only its SHA-256 hash in Redis, records when it was last used, and audits creation and revocation.
- An unknown or revoked token returns
401; a Redis outage returns503.
Managing tokens (session required)
GET /api/_ui/v1/tokenslists tokens:{ id, name, platforms (null = all), hint, createdAt, createdBy, lastUsedAt? }POST /api/_ui/v1/tokenswith{ "name": "ci", "platforms": ["ios"] }(omitplatformsfor all) returns201with{ token, record }DELETE /api/_ui/v1/tokens/{id}revokes a token immediately
Roles
Roles come from the OIDC claim named by OIDC_ROLES_CLAIM (default groups) at sign-in:
| Setting | Effect |
|---|---|
| neither group set | everyone signed in can edit and administer (the default) |
OIDC_EDITOR_GROUP |
only its members (and admins) can change configuration; others are view-only |
OIDC_ADMIN_GROUP |
only its members can delete platforms or versions and manage API tokens |
OIDC_PLATFORM_EDITORS |
e.g. ios:team-ios,team-mobile;web:team-web — writes to a listed platform also need one of its groups (admins are exempt); other platforms are unaffected |
Group settings are read on every request, so setting one also narrows sessions that already exist. Forbidden requests return 403. GET /api/auth/get-session includes permissions: { write, manage, restricted }, where restricted lists the platforms this user can't change. Groups are recorded at sign-in, so sessions from before platform groups were configured can't write restricted platforms until the user signs in again.
Deleting (admin)
DELETE /api/_ui/v1/platforms/{platform}removes a platform, all of its versions, and their history.DELETE /api/_ui/v1/platforms/{platform}/versions/{version}removes one version and its history.POST /api/{platform}with aversionslist that omits existing versions deletes them the same way: it needs the admin permission, runs the same dependency check, and removes their history.- Both return
409with the blocking schemas when a schema on another platform still@extendswhat would be deleted. Deletion is permanent and audited.
Response Format
- Success:
200 OKwith JSON data - Created:
201 Createdfor successful POST operations - Not Found:
404 Not Foundfor missing resources - Bad Request:
400 Bad Requestfor invalid input - Server Error:
500 Internal Server Errorfor unexpected errors
Endpoints
Platform Management
GET /api/schemas
Returns all platforms with their metadata.
Response:
[
{ "name": "mobile", "versions": ["1.0.0", "1.1.0"] },
{ "name": "web", "versions": ["2.0.0"] }
]GET /api/[platform]
Returns platform metadata including name, available versions, and optional kind.
kind is one of ios, android, web, service, or custom. It controls dashboard descriptions and icons; it does not change platform identifiers or configuration resolution. Older records may omit it and display as Custom.
Response:
{
"name": "mobile",
"versions": ["1.0.0", "1.1.0", "1.2.0"]
}Error Response (404):
{
"error": "Platform not found"
}POST /api/[platform]
Creates or updates platform metadata. An optional kind sets the platform type; omitting it preserves an existing type when updating versions. Invalid types return HTTP 400.
Request Body:
{
"name": "mobile",
"versions": ["1.0.0", "1.1.0"]
}Response:
{
"ok": true
}GET /api/[platform]/versions
Returns an array of all available versions for the platform.
Response:
["1.0.0", "1.1.0", "1.2.0"]Error Response (404):
{
"error": "Platform not found"
}POST /api/[platform]/versions
Adds a new version to the platform. The platform must already exist (create
it first with POST /api/[platform]).
The version must be a valid semantic version. Build metadata is supported, so
1.2.3+build.5 and 1.0.0-beta.1+exp.sha.5114f85 are both accepted. Versions
are limited to 128 characters and may contain only alphanumeric characters,
dots, hyphens, and plus signs — a value that only becomes valid semver after
trimming (e.g. " 1.2.3 ") is rejected rather than stored as-is.
Request Body:
{
"version": "1.2.3"
}Response:
{
"ok": true
}Error Response (400):
{
"error": "Missing \"version\" in body"
}Error Response (404):
{
"error": "Platform not found"
}Schema Management
GET /api/[platform]/[version]
Returns the resolved schema for the specified platform and version.
The [version] path segment accepts any version the write endpoints can
create, including build metadata. In a path segment + is a literal, so both
/api/ios/1.2.3+build.5 and the percent-encoded /api/ios/1.2.3%2Bbuild.5
resolve to the same version. Note that this does not hold in query strings,
where + means a space and must be sent as %2B.
Response:
{
"content": {
"feature": {
"enabled": true,
"config": { "timeout": 5000 }
}
},
"dependencies": ["core/1.0.0"],
"output": {
"feature": {
"enabled": true,
"config": { "timeout": 5000 }
},
"core": {
"version": "1.0.0",
"settings": { "debug": false }
}
}
}Error Response (404):
{
"error": "Version not found"
}Schema Features
@extends Directive
Schemas support composition using the @extends directive:
{
"@extends": "core/1.0.0",
"feature": {
"enabled": true,
"override": "custom-value"
}
}Dependency Resolution
- Exact versions:
core/1.2.3 - Latest:
core/latestorcore - Ranges:
core/^1.0.0,core/~1.2.0,core/>=1.0.0
Circular Dependency Detection
The system detects and prevents circular dependencies with clear error messages.
If schema A extends B and B extends A, the save will fail with a Circular dependency detected error.
Schema Validation
Before saving, schemas are validated:
- Content must be a plain JSON object (not array, string, null, etc.)
- All
@extendsreferences must resolve to existing platform/version pairs - Version ranges must match at least one available version
- Circular dependency chains are rejected at any depth
Cascade Updates
When a base schema is updated, all schemas that depend on it (via @extends) are automatically re-processed. The cascade uses visited-set tracking to prevent infinite loops.
Examples
All endpoints require an authenticated Paramtune session; the curl commands below omit the session cookie for brevity but will receive 401 Unauthorized without one.
Create a Platform
curl -X POST http://localhost:3000/api/mobile \
-H "Content-Type: application/json" \
-d '{"name": "mobile", "versions": ["1.0.0"]}'Add a Version
curl -X POST http://localhost:3000/api/mobile/versions \
-H "Content-Type: application/json" \
-d '{"version": "1.2.3"}'Get Platform Info
curl http://localhost:3000/api/mobileGet Schema
curl http://localhost:3000/api/mobile/1.2.3List All Versions
curl http://localhost:3000/api/mobile/versionsError Handling
All endpoints include proper error handling with:
- Detailed error messages
- Appropriate HTTP status codes
- Server-side logging for debugging
- CORS headers for cross-origin requests
Rate Limiting & Security
- CORS configured via
CORS_ORIGINenvironment variable - Security headers added via middleware
- Input validation on all endpoints
- All endpoints require an authenticated Paramtune session or, for reads, an API token; requests without either receive
401 Unauthorized
Caching
- All API responses include
Cache-Control: no-storeheaders - Redis provides backend caching for schema resolution
- Consider implementing CDN caching for production deployments
Dashboard platform creation
POST /api/_ui/v1/platforms accepts { "name": "customer-portal", "kind": "web" }, creates a platform with no versions, and returns HTTP 201. kind is optional. A duplicate name returns HTTP 409. This endpoint requires an authenticated session and the same write protections as other dashboard mutations.
The dashboard guides users through platform creation, a semantic version (initial suggestion 1.0.0), and an explicit configuration save. Loading the illustrative JSON example only edits the browser draft; it does not save or configure application behavior automatically.