API Reference
Complete reference for ContainerPub backend API endpoints.
Authentication
ContainerPub uses Keycloak OIDC for authentication. Tokens are obtained via the Direct Grant flow and validated via token introspection.
For detailed authentication documentation, see Authentication System.
POST /api/auth/register
Register a new user account. Creates user in both Keycloak and PostgreSQL.
Request:
{
"email": "user@example.com",
"password": "securepassword",
"first_name": "John",
"last_name": "Doe"
}
Response:
{
"message": "Account created successfully"
}
Flow:
- Validate email format and password
- Check registration feature flag (early access gating)
- Create user in Keycloak via Admin API (createUserWithCredentials)
- Store user in PostgreSQL with keycloak_user_id
- Store user_information in PostgreSQL
- Sync attributes to Keycloak
- Return success message
Notes:
- Password is managed by Keycloak (not stored in PostgreSQL)
- Email must be unique
- No tokens returned — user must login after registration
POST /api/auth/login
Authenticate via Keycloak and receive tokens. Legacy BCrypt users are auto-migrated to Keycloak.
Request:
{
"email": "user@example.com",
"password": "securepassword"
}
Response:
{
"access_token": "eyJhbGc...",
"refresh_token": "eyJhbGc...",
"expires_in": 300,
"token_type": "Bearer"
}
Flow:
- Try Keycloak Direct Grant login
- If successful: look up user by keycloak_user_id, check status, return tokens
- If Keycloak fails: try BCrypt fallback (legacy users)
- If BCrypt succeeds: auto-create user in Keycloak, backfill keycloak_user_id, sync attributes, login via Keycloak
- If both fail: return "Invalid credentials"
Status Check: Blocked or deleted users are rejected during login.
POST /api/auth/refresh
Refresh an expired access token using Keycloak's refresh_token grant.
Request:
{
"refresh_token": "eyJhbGc..."
}
Response:
{
"access_token": "eyJhbGc...",
"refresh_token": "eyJhbGc...",
"expires_in": 300,
"token_type": "Bearer"
}
POST /api/auth/logout
Logout and invalidate session via Keycloak.
Headers:
Authorization: Bearer <access-token>Request:
{
"refresh_token": "eyJhbGc..."
}
Response:
{
"message": "Logout successful"
}
POST /api/auth/reset-password
Initiate password reset via Keycloak native flow.
Request:
{
"email": "user@example.com"
}
Response:
{
"message": "If the email exists, a password reset link has been sent"
}
API Keys
API keys provide an additional layer of security for function invocations using HMAC-SHA256 signatures.
For detailed documentation on API keys, see API Keys & Signing.
POST /api/apikey/generate
Generate a new API key for a function.
Headers:
Authorization: Bearer <access-token>
Content-Type: application/json
Request:
{
"function_id": "function-uuid",
"validity": "1d", // Options: 1h, 1d, 1w, 1m, forever
"name": "Optional key name"
}
Response:
{
"message": "API key generated successfully",
"warning": "Store the private_key securely - it will not be shown again!",
"api_key": {
"uuid": "key-uuid",
"public_key": "base64-public-key",
"private_key": "base64-private-key",
"validity": "1d",
"expires_at": "2025-12-16T02:00:00Z",
"created_at": "2025-12-15T02:00:00Z"
}
}
GET /api/apikey/:function_id
Get API key info for a function.
Headers:
Authorization: Bearer <access-token>Response:
{
"has_api_key": true,
"api_key": {
"uuid": "key-uuid",
"public_key": "base64-public-key",
"validity": "1d",
"is_active": true,
"expires_at": "2025-12-16T02:00:00Z"
}
}
DELETE /api/apikey/:api_key_uuid/revoke
Revoke an API key (deactivate but keep in history).
Headers:
Authorization: Bearer <access-token>Response:
{
"message": "API key revoked successfully"
}
What it does:
- Marks the API key as inactive
- Records the revocation timestamp
- Key remains in database for audit history
- Cannot be reactivated
DELETE /api/apikey/:api_key_uuid
Delete an API key (remove from database).
Headers:
Authorization: Bearer <access-token>Response:
{
"message": "API key revoked successfully"
}
What it does:
- Permanently removes the API key from the database
- No audit trail remains
- Cannot be recovered
GET /api/apikey/:function_id/list
List all API keys for a function.
Headers:
Authorization: Bearer <access-token>Response:
{
"api_keys": [
{
"uuid": "key-uuid",
"validity": "1d",
"is_active": true,
"expires_at": "2025-12-16T02:00:00Z"
}
]
}
PUT /api/apikey/:api_key_uuid/roll
Extend an API key's expiration by its validity period.
Headers:
Authorization: Bearer <access-token>Response:
{
"message": "API key updated successfully"
}
What it does:
- Extends the expiration date by the key's validity period
- For example, if validity is 1d, it adds 1 day to the current expiration
- Useful for extending active keys without regenerating them
- Does not change the key UUID or secret
PUT /api/apikey/:api_key_uuid/update
Update an API key's validity period.
Headers:
Authorization: Bearer <access-token>
Content-Type: application/json
Request:
{
"validity": "1w", // New validity: 1h, 1d, 1w, 1m, forever
"name": "Updated key name" // Optional
}
Response:
{
"message": "API key updated successfully"
}
PUT /api/apikey/:api_key_uuid/enable
Re-enable a revoked API key.
Headers:
Authorization: Bearer <access-token>Response:
{
"message": "API key enabled successfully"
}
Notes:
- Only works on revoked keys (is_active = false)
- Sets is_active to true
- Does not change expiration date
Token Security
Tokens are issued and managed by Keycloak. The platform backend validates tokens via Keycloak's introspection endpoint on every request. A legacy JWT fallback exists during the migration period.
For details, see Authentication System.
Functions API
POST /api/functions/init
Initialize a new function (creates UUID and database record).
Headers:
Authorization: Bearer <access-token>
Content-Type: application/json
Request:
{
"name": "my_function",
"skip_signing": false // Optional, default: false
}
Response (New Function):
{
"message": "Function initialized successfully",
"id": "function-uuid",
"name": "my_function",
"status": "init",
"skip_signing": false,
"created_at": "2025-01-01T00:00:00Z"
}
Response (Existing Function):
{
"message": "Function already exists",
"id": "function-uuid",
"name": "my_function",
"status": "active",
"skip_signing": false,
"deployment_version": 3,
"created_at": "2025-01-01T00:00:00Z",
"already_exists": true
}
Notes:
- Must be called before deployment
- Creates function record with status init
- Returns existing function if name already exists for user
- Generates unique UUID for the function
POST /api/functions/deploy
Deploy a new function or update existing one.
Headers:
Authorization: Bearer <access-token>
Content-Type: multipart/form-data
Form Data:
- function_id - Function UUID (from init endpoint)
- archive - Function archive (tar.gz)
- env - Environment variables (JSON, optional)
Response:
{
"id": "function-id",
"name": "my-function",
"status": "deployed",
"url": "https://api.containerpub.dev/functions/function-id"
}
GET /api/functions
List all deployed functions for authenticated user.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- limit - Number of results (default: 10)
- offset - Pagination offset (default: 0)
Response:
{
"functions": [
{
"id": "function-id",
"name": "my-function",
"status": "active",
"created_at": "2025-01-01T00:00:00Z"
}
],
"total": 1
}
GET /api/functions/:id
Get function details.
Headers:
Authorization: Bearer <access-token>Response:
{
"id": "function-id",
"name": "my-function",
"status": "active",
"memory": 512,
"timeout": 30,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
DELETE /api/functions/:id
Delete a function.
Headers:
Authorization: Bearer <access-token>Response:
{
"message": "Function deleted successfully"
}
Function Execution
POST /api/functions/:id/invoke
Invoke a deployed function.
Headers:
Authorization: Bearer <access-token>
Content-Type: application/json
Request:
{
"body": {
"key": "value"
}
}
Response:
{
"execution_id": "exec-id",
"status": "success",
"result": {
"output": "result"
},
"duration_ms": 150
}
GET /api/functions/:id/executions
Get execution history for a function with pagination.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- page - Page number (default: 1)
- per_page - Results per page (default: 20, max: 100)
Response:
{
"executions": [
{
"uuid": "exec-uuid",
"status": "success",
"started_at": "2025-01-01T00:00:00Z",
"completed_at": "2025-01-01T00:00:05Z",
"duration_ms": 150
}
],
"page": 1,
"per_page": 20,
"total": 45,
"has_next": true
}
GET /api/functions/:id/executions/:executionUuid
Get detailed information about a specific execution.
Headers:
Authorization: Bearer <access-token>Response:
{
"execution": {
"uuid": "exec-uuid",
"function_uuid": "function-uuid",
"status": "success",
"started_at": "2025-01-01T00:00:00Z",
"completed_at": "2025-01-01T00:00:05Z",
"duration_ms": 150,
"invocation": {
"uuid": "invocation-uuid",
"timestamp": "2025-01-01T00:00:00Z",
"success": true,
"duration_ms": 150,
"error_message": null
},
"logs": [
{
"timestamp": "2025-01-01T00:00:01Z",
"level": "info",
"message": "Function started"
}
]
}
}
Versioning & Rollback
GET /api/functions/:id/deployments
Get deployment history for a function with pagination.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- page - Page number (default: 1)
- per_page - Results per page (default: 20, max: 100)
Response:
{
"function_uuid": "function-uuid",
"function_name": "my-function",
"function_status": "active",
"page": 1,
"per_page": 20,
"count": 5,
"total_pages": 1,
"has_next": false,
"deployments": [
{
"uuid": "deployment-uuid",
"version": 3,
"image_tag": "registry/my-function:v3",
"s3_key": "functions/uuid/v3.tar.gz",
"status": "active",
"is_active": true,
"created_at": "2025-01-03T00:00:00Z",
"deployed_at": "2025-01-03T00:01:00Z"
},
{
"uuid": "deployment-uuid-2",
"version": 2,
"image_tag": "registry/my-function:v2",
"s3_key": "functions/uuid/v2.tar.gz",
"status": "inactive",
"is_active": false,
"created_at": "2025-01-02T00:00:00Z",
"deployed_at": "2025-01-02T00:01:00Z"
}
]
}
POST /api/functions/:id/rollback
Rollback function to a previous deployment version.
Headers:
Authorization: Bearer <access-token>
Content-Type: application/json
Request:
{
"version": 2 // Version number to rollback to
}
Response:
{
"message": "Function rolled back successfully",
"function": {
"uuid": "function-uuid",
"name": "my-function",
"status": "active",
"active_version": 2
}
}
Notes:
- Rollback restores the specified version as the active deployment
- Previous active deployment is marked as inactive
- Function container is restarted with the rolled-back version
Deletion Management
POST /api/functions/:uuid/cancel-deletion
Cancel a pending deletion for a function.
Headers:
Authorization: Bearer <access-token>Response:
{
"success": true,
"message": "Deletion cancelled successfully",
"function": {
"uuid": "function-uuid",
"name": "my-function",
"status": "active"
}
}
Notes:
- Cancels all pending image deletions for the function
- Restores function status to active
- Can only cancel deletions with status pending
GET /api/functions/pending-deletions
Get all pending deletions for the authenticated user.
Headers:
Authorization: Bearer <access-token>Response:
{
"pending_deletions": [
{
"id": "pending-deletion-uuid",
"function_uuid": "function-uuid",
"function_name": "my-function",
"function_status": "pending_deletion",
"image_tag": "registry/my-function:v1",
"reason": "stale_function",
"deletion_date": "2025-02-01T00:00:00Z",
"days_remaining": 7,
"scheduled_at": "2025-01-25T10:30:00Z"
}
],
"count": 1
}
Notes:
- Returns only deletions with status pending
- Ordered by deletion date (earliest first)
- days_remaining calculated from current date
GET /api/functions/:uuid/deletion-status
Get deletion status for a specific function.
Headers:
Authorization: Bearer <access-token>Response:
{
"function_uuid": "function-uuid",
"function_name": "my-function",
"has_pending_deletion": true,
"deletion_info": {
"id": "pending-deletion-uuid",
"image_tag": "registry/my-function:v1",
"reason": "stale_function",
"deletion_date": "2025-02-01T00:00:00Z",
"days_remaining": 7,
"scheduled_at": "2025-01-25T10:30:00Z"
}
}
Logs API
GET /api/functions/:id/logs
Get function execution logs.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- limit - Number of lines (default: 100)
- since - Timestamp filter (ISO 8601)
Response:
{
"logs": [
{
"timestamp": "2025-01-01T00:00:00Z",
"level": "info",
"message": "Function started"
}
]
}
Error Responses
400 Bad Request
{
"error": "Invalid request",
"details": "Missing required field: name"
}
401 Unauthorized
{
"error": "Unauthorized",
"details": "Invalid or expired token"
}
Common Causes:
- Missing Authorization header
- Invalid access token
- Expired access token (use refresh token to get new one)
403 Forbidden
{
"error": "Forbidden",
"details": "Access denied"
}
404 Not Found
{
"error": "Not found",
"details": "Function not found"
}
500 Internal Server Error
{
"error": "Internal server error",
"details": "An unexpected error occurred"
}
Rate Limiting
- Requests per minute: 60
- Requests per hour: 1000
- Concurrent executions: 10 per function
Statistics API
GET /api/stats/overview
Get aggregated statistics for all user's functions.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- period - Time period: 1h, 24h, 7d, 30d (default: 24h)
Response:
{
"total_functions": 5,
"invocations_count": 1250,
"success_count": 1245,
"error_count": 5,
"average_latency_ms": 120,
"period": "24h"
}
GET /api/stats/overview/hourly
Get hourly chart data for all user's functions.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- hours - Number of hours (default: 24, max: 168)
Response:
{
"data": [
{
"hour": "2024-01-15T10:00:00Z",
"total_requests": 150,
"success_count": 148,
"error_count": 2,
"average_latency_ms": 120
}
],
"hours": 24
}
GET /api/stats/overview/daily
Get daily chart data for all user's functions.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- days - Number of days (default: 30, max: 90)
Response:
{
"data": [
{
"day": "2024-01-15T00:00:00Z",
"total_requests": 1500,
"success_count": 1495,
"error_count": 5,
"average_latency_ms": 115
}
],
"days": 30
}
GET /api/functions/:uuid/stats
Get statistics for a specific function.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- period - Time period: 1h, 24h, 7d, 30d (default: 24h)
Response:
{
"invocations_count": 250,
"success_count": 248,
"error_count": 2,
"average_latency_ms": 125,
"period": "24h"
}
GET /api/functions/:uuid/stats/hourly
Get hourly chart data for a specific function.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- hours - Number of hours (default: 24, max: 168)
Response:
{
"data": [
{
"hour": "2024-01-15T10:00:00Z",
"total_requests": 25,
"success_count": 24,
"error_count": 1,
"average_latency_ms": 125
}
],
"hours": 24
}
GET /api/functions/:uuid/stats/daily
Get daily chart data for a specific function.
Headers:
Authorization: Bearer <access-token>Query Parameters:
- days - Number of days (default: 30, max: 90)
Response:
{
"data": [
{
"day": "2024-01-15T00:00:00Z",
"total_requests": 250,
"success_count": 248,
"error_count": 2,
"average_latency_ms": 125
}
],
"days": 30
}
For detailed documentation on statistics and monitoring, see Statistics & Monitoring.
Health Check
GET /health
Check backend server health.
Response:
{
"status": "ok",
"timestamp": "2025-01-01T00:00:00Z"
}
No authentication required.
Next Steps
- Read Statistics & Monitoring for dashboard metrics documentation
- Read Architecture Overview
- Check CLI Documentation
- Explore Development Guide