CapRover API Documentation
This document provides information about the CapRover API endpoints, their parameters, and response formats. It is unofficial. It is mostly discovered using CapRover's codebase. It is mostly intended for LLMs to consume. Go to index.md for the Markdown version of this file.
API Response Format
All API responses follow a standard format:
{
"status": 100, // Status code (100 = success, 1000+ = error)
"description": "OK", // Status message
"data": {} // Optional response data
}
Common Concepts
Authentication
All API endpoints (except login) require authentication using a JWT token. Include the token in the x-captain-auth
header:
Headers:
x-captain-auth: <token>
Content-Type: application/json
To obtain a token, use the login endpoint:
POST /api/v2/login
Body: {
"password": "your-password",
"otpToken": "optional-otp-token"
}
Response:
{
"status": 100,
"description": "OK",
"data": {
"token": "jwt-token-string"
}
}
Status Codes:
- 100: Success
- 1105: Error - Wrong Password
- 1113: Error - Password Back Off (too many failed attempts)
- 1114: Error - OTP Required (if 2FA is enabled)
Status Codes
Code | Description |
---|---|
100 | Success |
101 | Success - Deploy Started |
102 | Success - Partial |
1000 | Error - Generic |
1001 | Error - Captain Not Initialized |
1101 | Error - User Not Initialized |
1102 | Error - Not Authorized |
1103 | Error - Already Exists |
1104 | Error - Bad Name |
1105 | Error - Wrong Password |
1106 | Error - Auth Token Invalid |
1107 | Error - Verification Failed |
1108 | Error - Illegal Operation |
1109 | Error - Build Error |
1110 | Error - Illegal Parameter |
1111 | Error - Not Found |
1112 | Error - Authentication Failed |
1113 | Error - Password Back Off |
1114 | Error - OTP Required |
1115 | Error - Pro API Key Invalid |
1116 | Error - Nginx Validation Failed |
App Naming Rules
When creating or updating apps, the app name must:
- Start with a lowercase letter
- End with a lowercase letter or number
- Contain only lowercase letters, numbers, and single hyphens
- Be less than 50 characters
- Not contain consecutive hyphens
- Not be 'captain' or 'registry'
App Management APIs
Get App Definitions
Retrieves all app definitions and system configuration.
GET /api/v2/user/apps/appDefinitions/
Description:
Retrieves a list of all application definitions and system configuration settings. This endpoint provides information about all apps registered in the CapRover instance, including their basic configuration and the system's root domain settings.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "OK",
"data": {
"appDefinitions": [
{
"appName": "my-app",
"hasPersistentData": false,
"instanceCount": 1,
"notExposeAsWebApp": false,
"forceSsl": true,
"containerHttpPort": 80,
"customDomain": "example.com",
"hasSsl": true,
"volumes": [
{
"hostPath": "/captain/data/my-app",
"containerPath": "/data"
}
],
"ports": [
{
"containerPort": "3000",
"hostPort": "5000"
}
],
"envVars": [
{
"key": "NODE_ENV",
"value": "production"
}
]
}
],
"rootDomain": "example.com",
"defaultNginxConfig": "nginx configuration template",
"forceSsl": true,
"hasRootSsl": true
}
}
Status Codes:
- 100: Success
- 1102: Error - Not Authorized (if authentication token is missing or invalid)
Notes:
- The response includes both app-specific configurations and system-wide settings
- Each app definition contains its complete configuration including volumes, ports, and environment variables
- The rootDomain field indicates the base domain for all apps if no custom domains are set
- The defaultNginxConfig contains the template used for generating Nginx configurations
- forceSsl and hasRootSsl indicate the SSL configuration status for the system
Register App
Creates a new application definition in CapRover.
POST /api/v2/user/apps/appDefinitions/register/
Description:
Creates a new application definition in CapRover with default settings. This endpoint registers a new app that can be customized later using the update endpoint.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"appName": "my-app", // Required: Name of the application
"projectId": "project-123", // Optional: ID of the project this app belongs to
"hasPersistentData": false // Optional: Whether the app has persistent data
}
Response:
{
"status": 100,
"description": "App Definition Saved",
"data": {
"appName": "my-app",
"hasPersistentData": false
}
}
Status Codes:
- 100: Success
- 1103: Error - App name already exists
- 1104: Error - Invalid app name format
Notes:
- If projectId is provided, the project must exist
- The app will be created with default settings that can be modified later using the update endpoint
- A placeholder image will be deployed initially
Update App
Updates an application's configuration.
POST /api/v2/user/apps/appDefinitions/update/
Description:
Modifies the configuration of an existing application. This endpoint allows you to update various aspects of the app including instance count, SSL settings, container configuration, volumes, ports, environment variables, and Git repository settings.
Authentication: Required - JWT token in x-captain-auth header
Important: Most fields are completely replaced, not merged. You must include ALL fields you want to keep in your update request, not just the ones you want to change.
Request Body:
{
"appName": "my-app", // Required: Name of the application
"projectId": "project-123", // Optional: ID of the project this app belongs to
"description": "My application", // Optional: Description of the application
"instanceCount": 2, // Optional: Number of instances to run (WARNING: if not provided, defaults to 0)
"notExposeAsWebApp": false, // Optional: Whether to expose the app as a web service
"forceSsl": true, // Optional: Whether to force SSL for the app
"containerHttpPort": 80, // Optional: HTTP port inside the container
"websocketSupport": false, // Optional: Whether to enable WebSocket support
"nodeId": "node-1", // Optional: ID of the node to deploy to
"customNginxConfig": "", // Optional: Custom Nginx configuration
"redirectDomain": "", // Optional: Domain to redirect to
"preDeployFunction": "", // Optional: Function to run before deployment
"serviceUpdateOverride": "", // Optional: Override for service update configuration
"appPushWebhook": { // Optional: Git repository configuration
"repoInfo": {
"repo": "https://github.com/user/repo.git", // Required: Git repository URL
"branch": "main", // Required: Branch to deploy
"user": "username", // Required if using password auth
"password": "password-or-token", // Required if using password auth
"sshKey": "-----BEGIN OPENSSH PRIVATE KEY-----..." // Required if using SSH auth
}
},
"envVars": [ // Optional: Environment variables
{
"key": "NODE_ENV",
"value": "production"
}
],
"volumes": [ // Optional: Volume mounts
{
"hostPath": "/captain/data/my-app",
"containerPath": "/data"
}
],
"ports": [ // Optional: Port mappings
{
"containerPort": "3000",
"hostPort": "5000"
}
],
"tags": [ // Optional: Application tags
{
"key": "environment",
"value": "production"
}
],
"httpAuth": { // Optional: HTTP authentication
"user": "admin",
"password": "secret"
},
"appDeployTokenConfig": { // Optional: App deployment token configuration
"enabled": true,
"appDeployToken": "optional-token"
}
}
Response:
{
"status": 100,
"description": "App Definition Updated",
"data": {
"appName": "my-app",
"instanceCount": 2,
"notExposeAsWebApp": false,
"forceSsl": true
}
}
Status Codes:
- 100: Success
- 1111: Error - App not found
- 1110: Error - Invalid parameters
- 1116: Error - Nginx validation failed
Notes:
- Only the
appName
field is required in the request body; all other fields are optional - CRITICAL WARNING: Most fields are completely replaced, not merged. You must include ALL fields you want to keep in your update request, not just the ones you want to change.
- CRITICAL WARNING: If
instanceCount
is not provided, it defaults to 0, which will stop the app.
Example of field replacement behavior:
// Current app configuration:
{
"instanceCount": 2,
"envVars": [{"key": "FOO", "value": "bar"}],
"ports": [{"containerPort": "3000", "hostPort": "80"}]
}
// If you want to change just instanceCount to 3, you MUST send:
{
"appName": "my-app",
"instanceCount": 3,
"envVars": [{"key": "FOO", "value": "bar"}],
"ports": [{"containerPort": "3000", "hostPort": "80"}]
}
// If you only send:
{
"appName": "my-app",
"instanceCount": 3
}
// This will clear out envVars and ports arrays because they weren't included!
Data Handling:
Arrays like
envVars
,volumes
,ports
, andtags
are completely replaced, not mergedSending empty arrays will clear existing values
Empty entries in arrays (like empty environment variables) are skipped
Git repository configuration (
appPushWebhook
) is completely replaced if providedIf
appPushWebhook
is provided but missing required fields, the entire webhook configuration is clearedHTTP authentication (
httpAuth
) and app deployment token (appDeployTokenConfig
) are completely replaced if providedIf
appDeployTokenConfig.enabled
is true but no token is provided, a random token is generatedIf
appDeployTokenConfig.enabled
is false, any existing token is clearedCustom domains, SSL certificates, and version history are preserved unless explicitly modified
Failed Nginx validation will automatically restore the previous configuration
Git Repository Configuration:
- Required fields: repository URL (
repo
), branch to deploy (branch
), and authentication - Authentication options:
- Username and password (both must be provided together)
- SSH key (must be in raw OpenSSH format, not encrypted)
- Webhook tokens are automatically managed and preserved during updates
- All credentials are securely encrypted before storage
- Required fields: repository URL (
Deployment Considerations:
- Changes to
instanceCount
will trigger a redeployment - Volume changes require app redeployment
- Environment variable changes apply immediately without redeployment
- Port mappings can be modified without redeployment
- SSL setting changes may require DNS configuration updates
- Changes to
Persistent Apps (with
hasPersistentData=true
):- Volumes cannot be modified
- Only one instance is allowed
- Node ID cannot be changed
The update operation is atomic - either all changes apply or none do
If an update fails, the system attempts to restore the previous configuration
Deploy App
Deploys an application from source code or a Docker image.
POST /api/v2/user/apps/appData/:appName
Description:
Deploys or updates an application using either a source code archive or a Docker image definition. The deployment process includes building the application (if source code is provided) and deploying it to the specified number of instances.
Authentication: Required - JWT token in x-captain-auth header
Request Options:
- Using Source Code Archive:
POST /api/v2/user/apps/appData/:appName
Content-Type: multipart/form-data
Form Data:
- sourceFile: Tarball file (.tar.gz) containing the application source code
- Using Docker Image Definition:
{
"captainDefinitionContent": "{\"schemaVersion\":2,\"dockerfileLines\":[\"FROM node:14-alpine\",\"WORKDIR /usr/src/app\",\"COPY ./ /usr/src/app\",\"RUN npm install --production\",\"ENV NODE_ENV production\",\"ENV PORT 80\",\"EXPOSE 80\",\"CMD [ \\\"npm\\\", \\\"start\\\" ]\"]}",
"gitHash": "optional-git-hash"
}
The captainDefinitionContent
can be specified in several ways:
- Using
dockerfileLines
(array of strings):
{
"schemaVersion": 2,
"dockerfileLines": [
"FROM node:14-alpine",
"WORKDIR /usr/src/app",
"COPY ./ /usr/src/app",
"RUN npm install --production",
"ENV NODE_ENV production",
"ENV PORT 80",
"EXPOSE 80",
"CMD [ \"npm\", \"start\" ]"
]
}
- Using
dockerfilePath
(path to Dockerfile):
{
"schemaVersion": 2,
"dockerfilePath": "./Dockerfile"
}
- Using
templateId
(predefined template):
{
"schemaVersion": 2,
"templateId": "node/14"
}
- Using
imageName
(existing Docker image):
{
"schemaVersion": 2,
"imageName": "nginx:latest"
}
Available templates include:
node
: Node.js applicationsphp
: PHP applicationspython-django
: Python Django applicationsruby-rack
: Ruby Rack applications
Response:
{
"status": 101,
"description": "Deploy Started",
"data": {
"appName": "my-app",
"deploymentId": "deploy-123"
}
}
Status Codes:
- 100: Success
- 101: Success - Deploy Started
- 1109: Error - Build Error
- 1111: Error - App not found
Notes:
- The source code archive must contain a valid captain-definition file or a Dockerfile
- Supported archive formats: .tar.gz
- The deployment process is asynchronous
- You can track deployment progress using the Get Build Logs endpoint
- The gitHash parameter is optional and used for tracking deployments
- The captainDefinitionContent must be a valid JSON string
- For Docker image deployments, the image must be accessible to the CapRover instance
- When using templates, the version number should be specified (e.g., "node/14" for Node.js 14)
- The deployment process is atomic - either all changes apply or none do
- If deployment fails, the system attempts to restore the previous configuration
Enable SSL for Base Domain
Enables HTTPS for the CapRover base domain using Let's Encrypt.
POST /api/v2/user/apps/appDefinitions/enablebasedomainssl/
Description:
Obtains and configures an SSL certificate for the CapRover base domain using Let's Encrypt. This endpoint enables HTTPS for the CapRover dashboard and all apps using the base domain.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"appName": "my-app"
}
Response:
{
"status": 100,
"description": "Base Domain SSL Enabled",
"data": {
"appName": "my-app",
"hasSsl": true,
"rootDomain": "example.com"
}
}
Status Codes:
- 100: Success
- 1111: Error - App not found
- 1116: Error - Nginx validation failed
- 1107: Error - SSL verification failed
Notes:
- The base domain must be properly configured in DNS
- Let's Encrypt rate limits apply (50 certificates per domain per week)
- Certificate renewal is automatic
- DNS propagation may take up to 24 hours
- The domain must be publicly accessible for Let's Encrypt verification
- This affects all apps using the base domain pattern (appname.example.com)
- The CapRover dashboard will also be accessible via HTTPS
Delete App
Deletes one or more applications and their associated resources.
POST /api/v2/user/apps/appDefinitions/delete/
Description:
Removes one or more applications from the CapRover instance. This endpoint can delete multiple apps at once and optionally remove their associated volumes. The operation is irreversible and will remove all app data unless volumes are preserved.
Authentication: Required - JWT token in x-captain-auth header
Request Body (Single App):
{
"appName": "my-app"
}
Request Body (Multiple Apps):
{
"appNames": ["app1", "app2"],
"volumes": ["volume1", "volume2"]
}
Response:
{
"status": 100,
"description": "App(s) Deleted Successfully",
"data": {
"deletedApps": ["app1", "app2"],
"deletedVolumes": ["volume1", "volume2"]
}
}
Status Codes:
- 100: Success
- 1111: Error - One or more apps not found
- 1108: Error - Illegal operation (e.g., trying to delete the CapRover app itself)
Notes:
- Deleting an app will remove all its deployments and configurations
- If volumes are specified, they will be permanently deleted
- If volumes are not specified, they will be preserved for potential future use
- The operation cannot be undone
- Apps with persistent data should be backed up before deletion
- The CapRover app itself cannot be deleted
- Custom domains associated with the app will be automatically removed
Rename App
Renames an existing application.
POST /api/v2/user/apps/appDefinitions/rename/
Description:
Renames an existing application while preserving its configuration, data, and relationships. This endpoint allows you to change an application's name while maintaining all its settings, volumes, and deployments.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"oldAppName": "old-app-name", // Required: Current name of the application
"newAppName": "new-app-name" // Required: New name for the application
}
Response:
{
"status": 100,
"description": "AppName is renamed",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error (if service is not running)
- 1104: Error - Bad Name (if new name doesn't follow naming rules)
- 1103: Error - Already Exists (if new name is already taken)
Notes:
- The new app name must follow the app naming rules:
- Start with a lowercase letter
- End with a lowercase letter or number
- Contain only lowercase letters, numbers, and single hyphens
- Be less than 50 characters
- Not contain consecutive hyphens
- Not be 'captain' or 'registry'
- The operation will fail if:
- The app is currently being built
- The service is not running
- The new name is already taken by another app
- The new name doesn't follow the naming rules
- The operation preserves:
- All app configurations
- Volumes and persistent data
- Environment variables
- Custom domains
- SSL certificates
- Webhook configurations
- If the app had SSL enabled, it will be automatically re-enabled for the new name
- The operation may take a few moments to complete
- All references to the app (e.g., in projects) are automatically updated
Implementation Details
- The rename operation is atomic and ensures data consistency
- The process involves:
- Validating the new app name
- Checking if the app is currently being built
- Verifying the service is running
- Removing the old service
- Updating the app definition with the new name
- Reinitializing the service with the new name
- Re-enabling SSL if it was previously enabled
- Webhook tokens are automatically regenerated for the new app name
- The operation includes a 2-second delay to ensure proper cleanup
- The app's service name in Docker is automatically updated
- All app metadata is preserved during the rename
Error Handling
If the rename operation fails, the system will return an error with one of these messages:
- "Service is not running!"
- "App Name is not allowed. Only lowercase letters and single hyphens are allowed"
- "App Name already exists. Please use a different name"
Example error response:
{
"status": 1104,
"description": "App Name is not allowed. Only lowercase letters and single hyphens are allowed",
"data": {}
}
Get App Logs
Retrieves application logs and deployment information.
GET /api/v2/user/apps/appData/:appName/logs
Description:
Retrieves logs and deployment information for a specific application. This endpoint can be used to monitor application status, debug issues, and track deployment progress.
Authentication: Required - JWT token in x-captain-auth header
Query Parameters:
since
: Optional - Unix timestamp to get logs since (default: 24 hours ago)limit
: Optional - Maximum number of log lines to return (default: 1000)follow
: Optional - Whether to stream logs in real-time (default: false)
Response:
{
"status": 100,
"description": "OK",
"data": {
"logs": [
{
"timestamp": "2024-03-20T10:00:00Z",
"message": "Container started successfully",
"type": "info"
},
{
"timestamp": "2024-03-20T10:00:01Z",
"message": "Application listening on port 3000",
"type": "info"
}
],
"deploymentStatus": {
"status": "running",
"lastDeployment": {
"id": "deploy-123",
"timestamp": "2024-03-20T09:55:00Z",
"status": "completed"
}
}
}
}
Status Codes:
- 100: Success
- 1111: Error - App not found
Notes:
- When
follow=true
, the response will stream logs in real-time - Logs are retained for 24 hours by default
- The response includes both application logs and deployment status
- Log types can be: info, error, warning, debug
- Timestamps are in ISO 8601 format
- The deployment status shows the current state and last deployment information
Get App Build Logs
Retrieves real-time build logs for an application during deployment.
GET /api/v2/user/apps/appData/:appName/
Description:
Retrieves build logs and deployment status for a specific application. This endpoint is used during the deployment process to stream build progress in real-time.
Authentication: Required - JWT token in x-captain-auth header
Headers:
x-captain-auth: <token>
x-namespace: captain
Query Parameters:
follow
: Optional - Whether to stream logs in real-time (default: false)since
: Optional - Unix timestamp to get logs since (default: 24 hours ago)limit
: Optional - Maximum number of log lines to return (default: 1000)
Response:
{
"status": 100,
"description": "App build status retrieved",
"data": {
"isAppBuilding": true,
"isBuildFailed": false,
"logs": {
"firstLineNumber": 1,
"lines": [
"Step 1/10: FROM node:14",
"Step 2/10: WORKDIR /app",
"Step 3/10: COPY package*.json ./"
]
}
}
}
Status Codes:
- 100: Success
- 1106: Error - Auth Token Invalid
- 1111: Error - App Not Found
Notes:
- When
follow=true
, the response will stream logs in real-time - The
since
parameter allows retrieving logs from a specific point in time - The
limit
parameter controls the maximum number of log lines returned - This endpoint uses a polling mechanism to simulate real-time updates
- Client should poll every 2 seconds while isAppBuilding is true
- firstLineNumber helps track log continuity
- Logs are returned in chronological order
- Build status is included in each response
- The endpoint automatically stops returning logs when the build completes
Polling Implementation
The client should implement a polling mechanism to retrieve build logs in real-time. Here's how the polling should work:
- Make an initial request to get the first set of logs
- Check the
isAppBuilding
field in the response - If
isAppBuilding
is true:- Wait 2 seconds
- Make another request
- Repeat until
isAppBuilding
becomes false
- If
isAppBuilding
is false:- Check
isBuildFailed
to determine build outcome - Stop polling
- Check
Example polling implementation:
async function pollBuildLogs(appName, token) {
while (true) {
const response = await fetch(`/api/v2/user/apps/appData/${appName}/`, {
headers: {
'x-captain-auth': token,
'x-namespace': 'captain'
}
});
const data = await response.json();
// Process logs
if (data.data.logs) {
console.log(data.data.logs.lines.join('\n'));
}
// Check if build is complete
if (!data.data.isAppBuilding) {
if (data.data.isBuildFailed) {
console.log('Build failed');
} else {
console.log('Build completed successfully');
}
break;
}
// Wait 2 seconds before next poll
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
The polling mechanism ensures that:
- Logs are retrieved in real-time as they become available
- The client doesn't miss any log entries
- The build status is properly tracked
- The polling stops automatically when the build completes
- Network resources are used efficiently with the 2-second delay
Example Usage:
# Poll for build logs with follow mode
while true; do
response=$(curl -s -H "x-captain-auth: $TOKEN" -H "x-namespace: captain" \
"http://your-server:3000/api/v2/user/apps/appData/myapp/?follow=true&limit=100")
# Process logs
echo "$response" | jq -r '.data.logs.lines[]'
# Check if build is complete
if [ "$(echo "$response" | jq -r '.data.isAppBuilding')" = "false" ]; then
break
fi
sleep 2
done
Status Codes:
- 100: Success
- 1106: Error - Auth Token Invalid
- 1111: Error - App Not Found
Notes:
- When
follow=true
, the response will stream logs in real-time - The
since
parameter allows retrieving logs from a specific point in time - The
limit
parameter controls the maximum number of log lines returned - This endpoint uses a polling mechanism to simulate real-time updates
- Client should poll every 2 seconds while isAppBuilding is true
- firstLineNumber helps track log continuity
- Logs are returned in chronological order
- Build status is included in each response
- The endpoint automatically stops returning logs when the build completes
Example Usage:
# Poll for build logs with follow mode
while true; do
response=$(curl -s -H "x-captain-auth: $TOKEN" -H "x-namespace: captain" \
"http://your-server:3000/api/v2/user/apps/appData/myapp/?follow=true&limit=100")
# Process logs
echo "$response" | jq -r '.data.logs.lines[]'
# Check if build is complete
if [ "$(echo "$response" | jq -r '.data.isAppBuilding')" = "false" ]; then
break
fi
sleep 2
done
Follow Parameter
The follow
parameter is used to enable real-time log streaming in several endpoints. When follow=true
, the response will stream logs in real-time instead of returning a single response.
Supported Endpoints:
- Get App Logs (
GET /api/v2/user/apps/appData/:appName/logs
) - Get App Build Logs (
GET /api/v2/user/apps/appData/:appName/
)
Implementation Details:
- When
follow=true
, the endpoint maintains an open connection and streams logs as they become available - The client should handle the streaming response appropriately
- For build logs, the client should poll every 2 seconds while
isAppBuilding
is true - The response includes a
firstLineNumber
to help track log continuity - Logs are returned in chronological order
- The streaming automatically stops when the build completes or when the app is no longer building
Example Usage with cURL:
# Stream app logs in real-time
curl -N -H "x-captain-auth: $TOKEN" \
"http://your-server:3000/api/v2/user/apps/appData/myapp/logs?follow=true"
# Stream build logs in real-time
curl -N -H "x-captain-auth: $TOKEN" \
"http://your-server:3000/api/v2/user/apps/appData/myapp/?follow=true"
Example Usage with JavaScript:
// Stream app logs
fetch('http://your-server:3000/api/v2/user/apps/appData/myapp/logs?follow=true', {
headers: {
'x-captain-auth': token
}
}).then(response => {
const reader = response.body.getReader();
const decoder = new TextDecoder();
function readStream() {
reader.read().then(({done, value}) => {
if (done) {
console.log('Stream complete');
return;
}
const text = decoder.decode(value);
console.log(text);
readStream();
});
}
readStream();
});
Notes:
- The
-N
flag in cURL disables buffering, which is required for real-time streaming - The response format remains the same as non-streaming requests
- The client should handle connection errors and reconnection if needed
- For build logs, the client should check
isAppBuilding
to know when to stop polling - The
firstLineNumber
helps track which logs are new since the last request - Logs are retained for 24 hours by default
- The streaming connection will automatically close when the operation completes
# Stream logs in real-time
curl -N -H "x-captain-auth: YOUR_JWT_TOKEN" \
"https://captain.yourdomain.com/api/v2/user/apps/appData/myapp/logs?follow=true"
# Stream build logs in real-time
curl -N -H "x-captain-auth: YOUR_JWT_TOKEN" \
"https://captain.yourdomain.com/api/v2/user/apps/appData/myapp/buildlogs?follow=true"
// Stream logs in real-time
fetch('https://captain.yourdomain.com/api/v2/user/apps/appData/myapp/logs?follow=true', {
headers: {
'x-captain-auth': 'YOUR_JWT_TOKEN'
}
}).then(response => {
const reader = response.body.getReader();
const decoder = new TextDecoder();
function readStream() {
reader.read().then(({done, value}) => {
if (done) {
console.log('Stream complete');
return;
}
const chunk = decoder.decode(value);
console.log('Received chunk:', chunk);
readStream();
});
}
readStream();
});
Streaming Response Format
When follow=true
, the response is a continuous stream of JSON objects, each representing a log entry. Here's how the streaming data looks:
{"status":100,"description":"OK","data":{"logs":[{"timestamp":"2024-03-20T10:00:00Z","message":"Container started successfully","type":"info"}]}}
{"status":100,"description":"OK","data":{"logs":[{"timestamp":"2024-03-20T10:00:01Z","message":"Application listening on port 3000","type":"info"}]}}
{"status":100,"description":"OK","data":{"logs":[{"timestamp":"2024-03-20T10:00:02Z","message":"Database connection established","type":"info"}]}}
{"status":100,"description":"OK","data":{"logs":[{"timestamp":"2024-03-20T10:00:03Z","message":"Cache initialized","type":"info"}]}}
{"status":100,"description":"OK","data":{"logs":[{"timestamp":"2024-03-20T10:00:04Z","message":"Request received: GET /api/users","type":"info"}]}}
{"status":100,"description":"OK","data":{"logs":[{"timestamp":"2024-03-20T10:00:05Z","message":"Error: Database query timeout","type":"error"}]}}
For build logs, the streaming format is similar but includes build-specific information:
{"status":100,"description":"OK","data":{"logs":{"lines":["Step 1/10 : FROM node:16-alpine","Step 2/10 : WORKDIR /app"],"firstLineNumber":1}}}
{"status":100,"description":"OK","data":{"logs":{"lines":["Step 3/10 : COPY package*.json .","Step 4/10 : RUN npm install"],"firstLineNumber":3}}}
{"status":100,"description":"OK","data":{"logs":{"lines":["Step 5/10 : COPY . .","Step 6/10 : RUN npm run build"],"firstLineNumber":5}}}
{"status":100,"description":"OK","data":{"logs":{"lines":["Step 7/10 : EXPOSE 3000","Step 8/10 : CMD [\"npm\", \"start\"]"],"firstLineNumber":7}}}
{"status":100,"description":"OK","data":{"logs":{"lines":["Successfully built abc123","Successfully tagged myapp:latest"],"firstLineNumber":9}}}
Each chunk in the stream:
- Is a complete JSON object
- Contains a status code (100 for success)
- Includes a description
- Contains the log data in the
data
field - May contain multiple log entries in a single chunk
- Is terminated with a newline character
The stream continues until:
- The operation completes
- The connection is closed
- An error occurs
Domain Management
Add Custom Domain
Adds a custom domain to an application.
POST /api/v2/user/apps/appDefinitions/customdomain/
Description:
Associates a custom domain with an application. This endpoint sets up the necessary DNS and Nginx configurations to route traffic from the custom domain to your application.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"appName": "my-app",
"customDomain": "example.com"
}
Response:
{
"status": 100,
"description": "Custom Domain Added",
"data": {
"appName": "my-app",
"customDomain": "example.com"
}
}
Status Codes:
- 100: Success
- 1111: Error - App not found
- 1116: Error - Nginx validation failed
Notes:
- The custom domain must be properly configured in your DNS settings
- DNS should point to your CapRover instance's IP address
- Wildcard subdomains are supported (e.g., *.example.com)
- Multiple custom domains can be added to a single app
- Changes may take up to 24 hours to propagate due to DNS caching
Enable SSL for Custom Domain
Enables HTTPS for a custom domain using Let's Encrypt.
POST /api/v2/user/apps/appDefinitions/enablecustomdomainssl/
Description:
Obtains and configures an SSL certificate for a custom domain using Let's Encrypt. This endpoint automates the SSL certificate issuance and renewal process.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"appName": "my-app",
"customDomain": "example.com"
}
Response:
{
"status": 100,
"description": "SSL Enabled for Custom Domain",
"data": {
"appName": "my-app",
"customDomain": "example.com",
"hasSsl": true
}
}
Status Codes:
- 100: Success
- 1111: Error - App not found
- 1116: Error - Nginx validation failed
- 1107: Error - SSL verification failed
Notes:
- The custom domain must be properly configured in DNS
- Let's Encrypt rate limits apply (50 certificates per domain per week)
- Certificate renewal is automatic
- DNS propagation may take up to 24 hours
- The domain must be publicly accessible for Let's Encrypt verification
Remove Custom Domain
Removes a custom domain from an application.
POST /api/v2/user/apps/appDefinitions/removecustomdomain/
Description:
Removes a custom domain configuration from an application. This endpoint disassociates a custom domain from your application and updates the necessary DNS and Nginx configurations.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"appName": "my-app", // Required: Name of the application
"customDomain": "example.com" // Required: Custom domain to remove
}
Response:
{
"status": 100,
"description": "Custom domain is removed for: my-app at example.com",
"data": {}
}
Status Codes:
- 100: Success
- 1111: Error - App not found
- 1000: Error - Generic error (if domain doesn't exist for the app)
Notes:
- The custom domain must be currently associated with the application
- The operation will remove all DNS and Nginx configurations for the domain
- If SSL was enabled for the domain, the SSL certificate will be removed
- If the domain was set as the redirect domain, the redirect will be removed
- If this was the last custom domain for the app, any redirect domain will be cleared
- The operation is immediate and doesn't require DNS propagation
- The domain can be reused for other applications after removal
Implementation Details
- The operation is atomic and ensures data consistency
- The process involves:
- Verifying the app exists
- Checking if the domain is associated with the app
- Removing the domain from the app's configuration
- Clearing any redirect settings if necessary
- Updating the Nginx configuration
- The operation preserves all other app configurations
- SSL certificates are automatically cleaned up
- The domain is immediately available for use with other apps
Error Handling
If the remove operation fails, the system will return an error with one of these messages:
- "Custom domain example.com does not exist in my-app"
- "App not found"
Example error response:
{
"status": 1000,
"description": "Custom domain example.com does not exist in my-app",
"data": {}
}
Project Management
Create Project
Creates a new project in CapRover.
POST /api/v2/user/projects/register
Description:
Creates a new project that can be used to organize and group related applications. Projects help manage multiple apps and their resources more effectively.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"id": "project-123", // Optional: Custom project ID (auto-generated if not provided)
"name": "my-project", // Required: Name of the project
"description": "Project description" // Optional: Project description
}
Response:
{
"status": 100,
"description": "Project Created",
"data": {
"id": "project-123",
"name": "my-project",
"description": "Project description",
"createdAt": "2024-03-20T10:00:00Z"
}
}
Get Projects
Retrieves all projects and their hierarchical structure.
GET /api/v2/user/projects
Description:
Retrieves a list of all projects in the CapRover instance. The projects are returned in a hierarchical order, with parent projects followed by their children.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "Projects are retrieved.",
"data": {
"projects": [
{
"id": "project-123",
"name": "parent-project",
"description": "Parent project description",
"parentProjectId": ""
},
{
"id": "project-456",
"name": "child-project",
"description": "Child project description",
"parentProjectId": "project-123"
}
]
}
}
Status Codes:
- 100: Success
Notes:
- Projects are returned in a hierarchical order (parent projects first, followed by their children)
- The parentProjectId field is empty for root-level projects
- Child projects reference their parent through the parentProjectId field
- The response includes all project metadata including ID, name, description, and parent relationship
- Projects can be used to organize apps and manage permissions
- The order is deterministic for consistent API responses
Delete Projects
POST /api/v2/user/projects/delete
Request Body:
{
"projectIds": ["project-id-1", "project-id-2"]
}
Update Project
Updates an existing project.
POST /api/v2/user/projects/update/
Description:
Updates an existing project's configuration. This endpoint allows you to modify the project's name, description, and parent project relationship.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"projectDefinition": {
"id": "project-123", // Required: ID of the project to update
"name": "updated-project", // Required: New name for the project
"description": "Updated description", // Optional: New project description
"parentProjectId": "parent-123" // Optional: ID of the parent project (empty string for root level)
}
}
Response:
{
"status": 100,
"description": "Project Saved",
"data": {}
}
Status Codes:
- 100: Success
- 1108: Error - Illegal Operation (if project ID is invalid or parent project doesn't exist)
- 1110: Error - Illegal Parameter (if project name is not allowed)
Notes:
- The project ID must be a valid UUID
- The project name must follow the naming rules:
- Start with a lowercase letter
- End with a lowercase letter or number
- Contain only lowercase letters, numbers, and single hyphens
- Be less than 50 characters
- Not contain consecutive hyphens
- Not be 'captain' or 'root'
- If parentProjectId is provided:
- It must be a valid UUID
- The parent project must exist
- It cannot be the same as the project's own ID
- The operation will fail if the project has child projects or contains applications
Rename Project
Renames an existing project.
POST /api/v2/user/projects/rename/
Description:
Renames an existing project while preserving its ID and relationships.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"projectId": "project-123", // Required: ID of the project to rename
"newName": "new-project-name" // Required: New name for the project
}
Response:
{
"status": 100,
"description": "Project Renamed",
"data": {}
}
Status Codes:
- 100: Success
- 1108: Error - Illegal Operation (if project ID is invalid)
- 1110: Error - Illegal Parameter (if new name is not allowed)
Notes:
- The project ID must be a valid UUID
- The new name must follow the same naming rules as project creation
- The operation preserves all project relationships and configurations
- The operation will fail if the project has child projects or contains applications
- The project's ID remains unchanged
- All references to the project (e.g., in applications) are automatically updated
One-Click Apps
Get One-Click App List
GET /api/v2/user/oneclick/template/list/
Description:
Retrieves a list of all available one-click apps from both the official CapRover repository and any custom repositories that have been added. This endpoint aggregates apps from all configured repositories and returns their metadata.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "All one click apps are retrieved",
"data": {
"oneClickApps": [
{
"baseUrl": "https://oneclickapps.caprover.com",
"name": "mysql",
"displayName": "MySQL",
"isOfficial": true,
"description": "MySQL Database Server",
"logoUrl": "https://oneclickapps.caprover.com/v4/logos/mysql.png"
}
]
}
}
Status Codes:
- 100: Success
Notes:
- The response includes apps from both official and custom repositories
- Each app entry contains metadata including name, display name, description, and logo URL
- The baseUrl field indicates which repository the app comes from
- The isOfficial field indicates whether the app is from the official CapRover repository
- Logo URLs are automatically resolved to full URLs if they are relative paths
- The default repository URL is https://oneclickapps.caprover.com
- Custom repositories can be added using the repository management endpoints
Get One-Click App Template
GET /api/v2/user/oneclick/template/app
Description:
Retrieves the detailed template configuration for a specific one-click app from a repository. This endpoint fetches the complete app template including deployment configuration, environment variables, and other settings needed to deploy the app.
Authentication: Required - JWT token in x-captain-auth header
Query Parameters:
appName
: Required - Name of the one-click app to retrieve (e.g., "mysql")baseDomain
: Required - Base URL of the repository containing the app (e.g., "https://oneclickapps.caprover.com")
Response:
{
"status": 100,
"description": "App template is retrieved",
"data": {
"appTemplate": {
"name": "mysql",
"displayName": "MySQL",
"description": "MySQL Database Server",
"version": "8.0",
"variables": [
{
"id": "mysql_root_password",
"label": "MySQL Root Password",
"description": "Password for the MySQL root user",
"type": "password",
"defaultValue": ""
}
],
"dockerfileLines": [
"FROM mysql:8.0",
"ENV MYSQL_ROOT_PASSWORD=${mysql_root_password}"
],
"captainDefinition": {
"schemaVersion": 2,
"dockerfilePath": "./Dockerfile"
}
}
}
}
Status Codes:
- 100: Success
- 1110: Error - Illegal Parameter (if baseDomain is not a registered repository)
- 1000: Error - Generic (if app template cannot be retrieved)
Notes:
- The baseDomain must be a registered one-click app repository
- The appName must exist in the specified repository
- The response includes the complete app template with all configuration details
- Template variables can be customized during app deployment
- The template includes Docker configuration and deployment settings
- Official repository events are tracked for analytics
- The default repository URL is https://oneclickapps.caprover.com
Deploy One-Click App
POST /api/v2/user/apps/appData/:appName
Description:
Deploys a one-click app using its template configuration. This endpoint takes a one-click app template and deploys it as a new application in your CapRover instance. The deployment process includes setting up the necessary configuration, environment variables, and volumes.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"appName": "my-mysql", // Required: Name for the deployed app
"oneClickAppName": "mysql", // Required: Name of the one-click app to deploy
"oneClickAppBaseUrl": "https://oneclickapps.caprover.com", // Required: Base URL of the one-click app repository
"variables": { // Optional: Variables to customize the app deployment
"mysql_root_password": "my-secure-password",
"mysql_database": "myapp"
},
"hasPersistentData": true, // Optional: Whether the app has persistent data (default: true for databases)
"notExposeAsWebApp": false, // Optional: Whether to expose the app as a web service
"instanceCount": 1, // Optional: Number of instances to deploy
"forceSsl": true, // Optional: Whether to force SSL for the app
"volumes": [ // Optional: Additional volumes to mount
{
"hostPath": "/captain/data/my-mysql",
"containerPath": "/var/lib/mysql"
}
],
"envVars": [ // Optional: Additional environment variables
{
"key": "MYSQL_CHARACTER_SET_SERVER",
"value": "utf8mb4"
}
]
}
Response:
{
"status": 101,
"description": "Deploy Started",
"data": {
"appName": "my-mysql",
"deploymentId": "deploy-123"
}
}
Status Codes:
- 100: Success
- 101: Success - Deploy Started
- 1109: Error - Build Error
- 1111: Error - App not found
- 1110: Error - Invalid parameters
Notes:
- The appName must follow the app naming rules (lowercase letters, numbers, hyphens)
- The oneClickAppName must exist in the specified repository
- Variables are used to customize the app's configuration during deployment
- For database apps, hasPersistentData is typically set to true
- The deployment process is asynchronous and can be monitored using the Get App Logs endpoint
- Environment variables and volumes can be added to customize the deployment
- SSL can be enabled for the app if forceSsl is set to true
- The app will be accessible at appname.yourdomain.com by default
- Custom domains can be added after deployment using the Add Custom Domain endpoint
Insert Repository
Adds a new one-click app repository.
POST /api/v2/user/oneclick/repositories/insert
Description:
Adds a new one-click app repository.
Authentication: Required - JWT token in x-captain-auth header
Delete Repository
Deletes a one-click app repository.
POST /api/v2/user/oneclick/repositories/delete
Description:
Deletes a one-click app repository.
Authentication: Required - JWT token in x-captain-auth header
Get Repositories
Retrieves all one-click app repositories.
GET /api/v2/user/oneclick/repositories/
Description:
Retrieves a list of all configured one-click app repositories.
Authentication: Required - JWT token in x-captain-auth header
System Management
Get System Info
GET /api/v2/user/system/info
Description:
Retrieves system information about the CapRover instance, including SSL configuration, domain settings, and other system-wide configurations.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "Captain info retrieved",
"data": {
"hasRootSsl": true, // Whether SSL is enabled for the root domain
"forceSsl": true, // Whether non-SSL traffic is forced to redirect to SSL
"rootDomain": "example.com", // The root domain configured for CapRover (empty if no custom domain)
"captainSubDomain": "captain" // The subdomain used for the CapRover dashboard
}
}
Status Codes:
- 100: Success
Notes:
- The rootDomain field will be empty if no custom domain is configured
- The captainSubDomain is used to access the CapRover dashboard (e.g., captain.example.com)
- hasRootSsl indicates whether SSL is enabled for the root domain
- forceSsl indicates whether non-SSL traffic is automatically redirected to HTTPS
- This endpoint is useful for checking the current system configuration
- The response can be used to determine if SSL needs to be enabled or configured
Get Version Info
GET /api/v2/user/system/versionInfo
Description:
Retrieves version information about the CapRover instance, including current version, latest available version, and update status. This endpoint checks both the official CapRover API and Docker Hub for version information.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "Version Info Retrieved",
"data": {
"currentVersion": "1.5.3",
"latestVersion": "1.5.4",
"changeLogMessage": "Bug fixes and improvements",
"canUpdate": true
}
}
Status Codes:
- 100: Success
Notes:
- For official CapRover images, version info is fetched from api-v1.caprover.com
- For unofficial images, version info is fetched from Docker Hub
- The response includes the current installed version and latest available version
- changeLogMessage is only available for official CapRover images
- canUpdate indicates whether an update is available
- The endpoint automatically falls back to Docker Hub if the official API is unavailable
- Version information is used to determine if updates are available
Create Backup
Creates a backup of the CapRover instance including all app data, configurations, and system settings.
POST /api/v2/user/system/createbackup/
Description:
Creates a comprehensive backup of the CapRover instance, including all application data, configurations, SSL certificates, and system settings. The backup is stored as a tar file and can be used to restore the instance to its current state.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "Backup created.",
"data": {
"downloadToken": "token-string" // Token to download the backup file
}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error
- 1001: Error - Captain not initialized
- 1102: Error - Not authorized
Notes:
- The backup includes all app data, configurations, and system settings
- The backup file is automatically deleted after 2 hours
- The backup process is atomic and ensures data consistency
- The backup includes SSL certificates and Let's Encrypt configurations
- The backup can be used to restore the instance on a new server
- The backup file name includes timestamp and IP address for identification
- The backup process locks the system to prevent concurrent operations
- The backup is stored in the /captain/downloads directory
- The downloadToken can be used to retrieve the backup file
Change Root Domain
Changes the root domain for the CapRover instance.
POST /api/v2/user/system/changerootdomain
Description:
Changes the root domain for the CapRover instance. This affects all apps using the base domain pattern (appname.rootdomain.com) and the CapRover dashboard. The operation may require DNS configuration updates and can affect SSL certificates.
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"rootDomain": "new-domain.com", // Required: The new root domain
"force": false // Optional: Force change even if SSL is enabled
}
Response:
{
"status": 100,
"description": "Root domain changed.",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error (e.g., bad domain name)
- 1108: Error - Illegal operation (e.g., local registry exists)
- 1116: Error - Nginx validation failed
Notes:
- The root domain must be properly configured in DNS
- The domain name must be at least 3 characters long
- The domain name cannot contain special characters (/, :, %, space, )
- If SSL is enabled for the root domain, the change will be blocked unless force=true
- When force=true, SSL will be disabled for the root domain and all apps
- The operation cannot be performed if a local Docker registry exists
- DNS changes may take up to 24 hours to propagate
- The CapRover dashboard will be accessible at captain.new-domain.com
- All apps will be accessible at appname.new-domain.com
- The operation requires DNS verification before proceeding
Enable SSL for Captain
POST /api/v2/user/system/enablessl
Description:
Enables HTTPS for the CapRover dashboard using Let's Encrypt. This endpoint obtains and configures an SSL certificate for the CapRover dashboard domain (captain.yourdomain.com).
Authentication: Required - JWT token in x-captain-auth header
Request Body:
{
"emailAddress": "admin@example.com" // Required: Email address for Let's Encrypt notifications
}
Response:
{
"status": 100,
"description": "Root SSL Enabled.",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error (e.g., invalid email address)
- 1116: Error - Nginx validation failed
- 1107: Error - SSL verification failed
Notes:
- The email address must be valid and properly formatted
- The root domain must be properly configured in DNS
- Let's Encrypt rate limits apply (50 certificates per domain per week)
- Certificate renewal is automatic
- DNS propagation may take up to 24 hours
- The domain must be publicly accessible for Let's Encrypt verification
- After enabling SSL, there is a 7-second delay before the HTTPS endpoint becomes available
- This is a prerequisite for enabling SSL on custom domains for apps
Docker Registry Management
Get Registries
GET /api/v2/user/registries/
Description:
Retrieves a list of all configured Docker registries and the default push registry ID. This endpoint provides information about both local and remote Docker registries that are configured in the CapRover instance.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "All registries retrieved",
"data": {
"registries": [
{
"id": "registry-uuid",
"registryUser": "username",
"registryPassword": "password",
"registryDomain": "registry.example.com",
"registryImagePrefix": "prefix/",
"registryType": "REMOTE_REG"
}
],
"defaultPushRegistryId": "registry-uuid"
}
}
Status Codes:
- 100: Success
Notes:
- The response includes both local and remote registries
- Each registry entry contains authentication details and configuration
- The registryType can be either "LOCAL_REG" or "REMOTE_REG"
- The defaultPushRegistryId indicates which registry is used for pushing images by default
- Registry passwords are stored encrypted in the database but returned decrypted in the API response
- Local registries cannot be edited or deleted through the API
- The registryDomain for Docker Hub must be specified as "index.docker.io"
- The registryImagePrefix is optional and can be used to namespace images
Get Unused Images
GET /api/v2/user/apps/appDefinitions/unusedImages
Description:
Retrieves a list of Docker images that are not currently in use by any application. This endpoint helps identify images that can be safely removed to free up disk space. The endpoint considers an image as unused if it's not associated with any current or recent deployments of any application.
Authentication: Required - JWT token in x-captain-auth header
Query Parameters:
mostRecentLimit
: Optional - Number of most recent versions to keep for each app (default: 0)
Response:
{
"status": 100,
"description": "Unused images retrieved.",
"data": {
"unusedImages": [
{
"id": "sha256:abc123...",
"tags": ["img-captain-myapp:8", "img-captain-myapp:9"]
}
]
}
}
Status Codes:
- 100: Success
- 1110: Error - Illegal Parameter (if mostRecentLimit is negative)
Notes:
- The mostRecentLimit parameter determines how many recent versions of each app to preserve
- Images are considered unused if they're not associated with any current or recent deployments
- The response includes both the image ID and associated tags
- This endpoint is useful for disk cleanup operations
- The endpoint is used by the automated disk cleanup system
- Images returned by this endpoint can be safely deleted using the Delete Images endpoint
- The endpoint checks against all registered applications in the system
- Image tags are preserved in the response for identification purposes
System Management
Force SSL
Forces SSL for all applications.
POST /api/v2/user/system/forcessl/
Description:
Forces SSL for all applications by redirecting HTTP traffic to HTTPS.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "SSL forced for all apps",
"data": {}
}
Get Load Balancer Info
Retrieves load balancer configuration information.
GET /api/v2/user/system/loadbalancerinfo/
Description:
Retrieves information about the load balancer configuration, including SSL settings and domain configurations.
Authentication: Required - JWT token in x-captain-auth header
Response:
{
"status": 100,
"description": "Load balancer info retrieved",
"data": {
"hasRootSsl": true,
"forceSsl": true,
"rootDomain": "example.com"
}
}
Disk Cleanup
Manages disk cleanup operations.
GET /api/v2/user/system/diskcleanup/
POST /api/v2/user/system/diskcleanup/
Description:
Retrieves and manages disk cleanup operations, including unused images and volumes.
Authentication: Required - JWT token in x-captain-auth header
Response (GET):
{
"status": 100,
"description": "Disk cleanup info retrieved",
"data": {
"unusedImages": [
{
"id": "sha256:abc123...",
"tags": ["img-captain-myapp:8"]
}
]
}
}
Netdata Monitoring
Manages Netdata monitoring configuration.
GET /api/v2/user/system/netdata/
POST /api/v2/user/system/netdata/
Description:
Retrieves and configures Netdata monitoring settings. Netdata is a real-time performance and health monitoring system that provides detailed metrics about your CapRover instance.
Authentication: Required - JWT token in x-captain-auth header
Get Netdata Configuration
GET /api/v2/user/system/netdata/
Response:
{
"status": 100,
"description": "Netdata info retrieved",
"data": {
"isEnabled": true,
"netDataUrl": "captain.example.com/net-data-monitor"
}
}
Status Codes:
- 100: Success
Notes:
- The netDataUrl is constructed using the captain subdomain and root domain
- The URL path is determined by the
netDataRelativePath
constant (/net-data-monitor) - The response indicates whether Netdata monitoring is enabled
- The URL can be used to access the Netdata monitoring dashboard
Update Netdata Configuration
POST /api/v2/user/system/netdata/
Request Body:
{
"netDataInfo": {
"isEnabled": true
}
}
Response:
{
"status": 100,
"description": "Netdata info is updated",
"data": {}
}
Status Codes:
- 100: Success
Notes:
- The netDataUrl field in the request is ignored as it's automatically generated
- Changes to the configuration may require the Netdata container to be restarted
- The Netdata container name is defined by the
netDataContainerName
constant - The service runs on the CapRover overlay network
- If Netdata is not running, API requests may fail with a specific error message
Implementation Details
- The Netdata service runs in a Docker container named
captain-netdata-container
- The service is accessible through the path defined by
netDataRelativePath
(/net-data-monitor) - The service is part of the CapRover overlay network (
captain-overlay-network
) - If the Netdata container is not running, API requests will fail with a specific error message
- The configuration is stored in the CapRover data store
- The service URL is automatically constructed using the captain subdomain and root domain
Error Handling
If the Netdata container is not running, API requests may fail with the following error:
Something went wrong... err: NetData is not running! Are you sure you have started it?
This error occurs when the system cannot resolve the Netdata container hostname or when the container is not running.
GoAccess Analytics
Manages GoAccess analytics configuration and data.
GET /api/v2/user/system/goaccess/
POST /api/v2/user/system/goaccess/
GET /api/v2/user/system/goaccess/:appName/files
GET /api/v2/user/system/goaccess/:appName/files/:file
Description:
Retrieves and configures GoAccess analytics settings and data for applications. GoAccess is a real-time web log analyzer that provides detailed analytics about your application's web traffic.
Authentication: Required - JWT token in x-captain-auth header
Get GoAccess Configuration
GET /api/v2/user/system/goaccess/
Response:
{
"status": 100,
"description": "GoAccess info retrieved",
"data": {
"isEnabled": true,
"data": {
"rotationFrequencyCron": "0 0 1 * *", // Monthly rotation by default
"logRetentionDays": 30 // Optional: Number of days to retain logs
}
}
}
Status Codes:
- 100: Success
Notes:
- The rotationFrequencyCron uses standard cron syntax
- Default rotation is set to monthly (0 0 1 * *)
- logRetentionDays is optional and defaults to -1 (no retention limit)
Update GoAccess Configuration
POST /api/v2/user/system/goaccess/
Request Body:
{
"goAccessInfo": {
"isEnabled": true,
"data": {
"rotationFrequencyCron": "0 0 1 * *",
"logRetentionDays": 30
}
}
}
Response:
{
"status": 100,
"description": "GoAccess info is updated",
"data": {}
}
Status Codes:
- 100: Success
- 1110: Error - Illegal Parameter (if cron schedule is invalid)
Notes:
- The cron schedule must be valid
- Changes to the configuration may require the GoAccess container to be restarted
- The GoAccess container name is defined by the
goAccessContainerName
constant - The service runs on the CapRover overlay network
- Log files are stored in the nginx shared logs directory
Get Application Log Files
GET /api/v2/user/system/goaccess/:appName/files
Description:
Retrieves a list of available log files and reports for a specific application.
Response:
{
"status": 100,
"description": "GoAccess info retrieved",
"data": [
{
"domainName": "myapp.example.com",
"name": "access.log.html",
"lastModifiedTime": "2024-03-20T10:00:00Z",
"url": "/user/system/goaccess/myapp/files/access.log.html"
},
{
"domainName": "myapp.example.com",
"name": "access.log--Live.html",
"lastModifiedTime": "2024-03-20T10:00:00Z",
"url": "/user/system/goaccess/myapp/files/access.log--Live.html"
}
]
}
Status Codes:
- 100: Success
- 1000: Error - Generic error (if appName is invalid)
- 1000: Error - Generic error (if GoAccess is not enabled)
Notes:
- Returns both static reports and live report URLs
- Live reports are dynamically generated
- Reports are sorted by last modified time (newest first)
- Each report includes the domain name it's associated with
- The URL can be used to access the report directly
Get Log File Content
GET /api/v2/user/system/goaccess/:appName/files/:file
Description:
Retrieves the content of a specific log file or report.
Parameters:
appName
: Name of the applicationfile
: Name of the log file or report
Response:
- HTML content for the requested report
- 404 Not Found if the file doesn't exist
Status Codes:
- 200: Success
- 404: Not Found
Notes:
- For live reports (ending in --Live.html), the content is dynamically generated
- The report is generated using the catchupLog.sh script
- Files are served from the nginx shared logs directory
- The GoAccess container must be running to generate live reports
Implementation Details
- The GoAccess service runs in a Docker container named
captain-goaccess-container
- Log files are stored in the nginx shared logs directory
- The service uses a cron job for log rotation
- Live reports are generated on-demand
- The service is part of the CapRover overlay network
- Log retention can be configured through the logRetentionDays parameter
- The service uses the official GoAccess Docker image (caprover/goaccess:1.9.3)
Nginx Configuration
Manages Nginx configuration settings for the CapRover instance.
GET /api/v2/user/system/nginxconfig/
POST /api/v2/user/system/nginxconfig/
Description:
Retrieves and updates Nginx configuration settings for the CapRover instance. This endpoint allows you to customize both the base Nginx configuration and the CapRover-specific configuration.
Authentication: Required - JWT token in x-captain-auth header
Get Nginx Configuration
GET /api/v2/user/system/nginxconfig/
Response:
{
"status": 100,
"description": "Nginx config retrieved",
"data": {
"baseConfig": {
"byDefault": "default base nginx configuration",
"customValue": "custom base nginx configuration"
},
"captainConfig": {
"byDefault": "default captain nginx configuration",
"customValue": "custom captain nginx configuration"
}
}
}
Status Codes:
- 100: Success
Notes:
- The baseConfig contains the main Nginx configuration
- The captainConfig contains CapRover-specific configuration
- Both configurations include default and custom values
- The configuration affects all applications and services
Update Nginx Configuration
POST /api/v2/user/system/nginxconfig/
Request Body:
{
"baseConfig": {
"customValue": "custom base nginx configuration"
},
"captainConfig": {
"customValue": "custom captain nginx configuration"
}
}
Response:
{
"status": 100,
"description": "Nginx config is updated",
"data": {}
}
Status Codes:
- 100: Success
- 1116: Error - Nginx validation failed
Notes:
- Changes are validated before being applied
- If validation fails, the previous configuration is automatically restored
- The configuration affects all applications and services
- Changes may require a restart of the Nginx container
- The configuration is stored in the CapRover data store
- Custom configurations should follow Nginx syntax rules
- The base configuration includes global settings like worker processes and SSL settings
- The captain configuration includes app-specific settings and routing rules
Implementation Details
- The Nginx service runs in a Docker container named
captain-nginx
- Configuration files are stored in the following locations:
- Base config:
/captain/data/nginx/nginx.conf
- Root config:
/captain/data/nginx/conf.d/captain-root
- Per-app configs:
/captain/data/nginx/conf.d/
- Base config:
- The service is part of the CapRover overlay network
- Configuration changes are validated using
nginx -t
- If validation fails, changes are automatically reverted
- The service supports both HTTP and HTTPS traffic
- WebSocket support can be enabled per application
- Custom error pages can be configured
- Access logs are stored in
/var/log/nginx/access.log
- Error logs are stored in
/var/log/nginx/error.log
Error Handling
If the Nginx configuration validation fails, the system will:
- Log the validation error
- Automatically revert to the previous configuration
- Return a 1116 error code with the validation error message
Example error response:
{
"status": 1116,
"description": "Nginx validation failed",
"data": {
"error": "unknown directive 'invalid_directive' in /etc/nginx/nginx.conf:10"
}
}
Node Management
Manages cluster nodes in the CapRover Docker Swarm.
GET /api/v2/user/system/nodes/
POST /api/v2/user/system/nodes/
Description:
Retrieves and manages cluster node configurations in the Docker Swarm. This endpoint allows you to view node information and add new nodes to the cluster.
Authentication: Required - JWT token in x-captain-auth header
Get Nodes Information
GET /api/v2/user/system/nodes/
Response:
{
"status": 100,
"description": "Node info retrieved",
"data": {
"nodes": [
{
"nodeId": "node-id-string",
"type": "manager",
"isLeader": true,
"hostname": "node-hostname",
"architecture": "x86_64",
"operatingSystem": "linux",
"nanoCpu": 4000000000,
"memoryBytes": 8589934592,
"dockerEngineVersion": "20.10.0",
"ip": "192.168.1.100",
"state": "ready",
"status": "active"
}
]
}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error (if no nodes are found)
Notes:
- Returns information about all nodes in the cluster
- Each node entry includes detailed system information
- The type field can be either "manager" or "worker"
- isLeader indicates if the node is the swarm leader
- state indicates if the node is "ready" or "down"
- status can be "active", "drain", or "pause"
- Resource information includes CPU and memory allocation
Add Node to Cluster
POST /api/v2/user/system/nodes/
Request Body:
{
"nodeType": "manager", // Required: Either "manager" or "worker"
"privateKey": "ssh-private-key", // Required: SSH private key for authentication
"remoteNodeIpAddress": "192.168.1.101", // Required: IP address of the node to add
"captainIpAddress": "192.168.1.100", // Required: IP address of the CapRover node
"sshPort": 22, // Optional: SSH port (default: 22)
"sshUser": "root" // Optional: SSH username (default: "root")
}
Response:
{
"status": 100,
"description": "Docker node is successfully joined.",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error
- 1110: Error - Illegal Parameter (if nodeType is invalid)
Notes:
- The node must have Docker installed and running
- The SSH user must have permissions to run Docker commands
- The private key must be in the correct format
- The node will be added to the Docker Swarm cluster
- Manager nodes can participate in swarm management
- Worker nodes can only run containers
- The operation requires network connectivity between nodes
- The node must be accessible via SSH
- The operation may take several minutes to complete
Implementation Details
- Nodes are managed through Docker Swarm
- The cluster must have at least one manager node
- Manager nodes participate in the Raft consensus
- Worker nodes can be added for horizontal scaling
- Node state is monitored and reported
- Resource allocation is tracked per node
- The system supports both Linux and Windows nodes
- Node labels can be used for service placement
- The cluster supports automatic failover
- Node health is monitored continuously
Error Handling
If node addition fails, the system will return an error with one of these messages:
- "Node type should be either manager or worker"
- "Private Key, Captain IP address, remote IP address and remote username should all be present"
- "There is no default Docker Registry. You need a repository for your images before adding nodes"
- "SSH Connection error!!"
Example error response:
{
"status": 1000,
"description": "Node type should be either manager or worker",
"data": {}
}
Self-Hosted Registry
Manages the self-hosted Docker registry for the CapRover instance.
POST /api/v2/user/system/selfhostregistry/enableregistry/
POST /api/v2/user/system/selfhostregistry/disableregistry/
Description:
Enables or disables the self-hosted Docker registry for the CapRover instance. The self-hosted registry allows you to store and manage Docker images locally, reducing external dependencies and improving deployment speed.
Authentication: Required - JWT token in x-captain-auth header
Enable Registry
POST /api/v2/user/system/selfhostregistry/enableregistry/
Response:
{
"status": 100,
"description": "Local registry is created.",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error
- 1108: Error - Illegal operation (if a local registry already exists)
- 1112: Error - Authentication failed (if registry authentication fails)
Notes:
- The registry is created with a randomly generated password
- The registry is accessible at registry.yourdomain.com:5000
- SSL is automatically enabled if root SSL is enabled
- The registry uses htpasswd authentication
- The registry supports image deletion
- The registry is part of the CapRover overlay network
- The registry runs in a Docker container named
captain-registry
- The registry data is persisted in the CapRover data store
Disable Registry
POST /api/v2/user/system/selfhostregistry/disableregistry/
Response:
{
"status": 100,
"description": "Local registry is removed.",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error
- 1110: Error - Illegal Parameter (if registry is set as default push registry)
Notes:
- The registry container and data will be removed
- The operation cannot be performed if the registry is set as the default push registry
- SSL certificates will be removed if they were created
- The registry domain will be removed from Nginx configuration
- All local images will be lost
- The operation is irreversible
Implementation Details
- The registry service runs in a Docker container named
captain-registry
- The registry is accessible through the path defined by
registrySubDomain
(registry) - The registry port is defined by
registrySubDomainPort
(5000) - The registry uses the official Docker Registry image
- The registry supports both HTTP and HTTPS
- The registry uses htpasswd for authentication
- The registry supports image deletion through the
REGISTRY_STORAGE_DELETE_ENABLED
flag - The registry data is stored in the CapRover data store
- The registry is part of the CapRover overlay network
- The registry supports both Linux and Windows containers
SSL Configuration
If root SSL is enabled, the registry will automatically:
- Obtain an SSL certificate from Let's Encrypt
- Configure the registry to use HTTPS
- Set up Nginx to proxy HTTPS traffic to the registry
- Configure automatic certificate renewal
Error Handling
If enabling the registry fails, the system will return an error with one of these messages:
- "There is already a local registry set up!"
- "Root must have SSL before enabling ssl for docker registry"
- "Registry authentication failed"
Example error response:
{
"status": 1108,
"description": "There is already a local registry set up!",
"data": {}
}
Theme Management
Manages themes for the CapRover dashboard.
POST /api/v2/user/themes/setcurrent/
POST /api/v2/user/themes/update/
POST /api/v2/user/themes/delete/
GET /api/v2/user/themes/all/
GET /api/v2/public/themes/current
Description:
Manages themes for the CapRover dashboard. Themes control the appearance and behavior of the CapRover interface. The system includes built-in themes and supports custom themes.
Authentication: Required - JWT token in x-captain-auth header (except for public endpoints)
Set Current Theme
POST /api/v2/user/themes/setcurrent/
Request Body:
{
"themeName": "theme-name" // Required: Name of the theme to set as current
}
Response:
{
"status": 100,
"description": "Current theme is stored.",
"data": {}
}
Status Codes:
- 100: Success
- 1110: Error - Illegal Parameter (if theme not found)
Update Theme
POST /api/v2/user/themes/update/
Request Body:
{
"oldName": "old-theme-name", // Optional: Name of the theme to update (omit for new theme)
"name": "theme-name", // Required: Name of the theme
"content": "theme-content", // Required: Theme content (CSS/JS)
"extra": "extra-content", // Optional: Additional theme content
"headEmbed": "head-content" // Optional: Content to embed in HTML head
}
Response:
{
"status": 100,
"description": "Theme is stored.",
"data": {}
}
Status Codes:
- 100: Success
- 1110: Error - Illegal Parameter (if theme name already exists or trying to edit built-in theme)
Delete Theme
POST /api/v2/user/themes/delete/
Request Body:
{
"themeName": "theme-name" // Required: Name of the theme to delete
}
Response:
{
"status": 100,
"description": "Theme is deleted.",
"data": {}
}
Status Codes:
- 100: Success
- 1110: Error - Illegal Parameter (if theme not found or trying to delete built-in theme)
Get All Themes
GET /api/v2/user/themes/all/
Response:
{
"status": 100,
"description": "Themes are retrieved.",
"data": {
"themes": [
{
"name": "theme-name",
"content": "theme-content",
"extra": "extra-content",
"headEmbed": "head-content",
"builtIn": true
}
]
}
}
Status Codes:
- 100: Success
Get Current Theme (Public)
GET /api/v2/public/themes/current
Description:
Retrieves the current theme configuration (no authentication required).
Response:
{
"status": 100,
"description": "Current theme is retrieved.",
"data": {
"theme": {
"name": "theme-name",
"content": "theme-content",
"extra": "extra-content",
"headEmbed": "head-content",
"builtIn": true
}
}
}
Status Codes:
- 100: Success
Implementation Details
- Themes are stored in the CapRover data store
- Built-in themes are loaded from the
/template/themes
directory - Theme files use a special format with fields prefixed by
###CapRoverTheme.
- The theme content can include CSS, JavaScript, and HTML
- The headEmbed field allows injecting content into the HTML head
- The extra field can be used for additional theme resources
- Built-in themes cannot be modified or deleted
- Theme changes are applied immediately
- The current theme is persisted across restarts
Theme File Format
Theme files use a special format with fields prefixed by ###CapRoverTheme.
:
###CapRoverTheme.name:
Theme Name
###CapRoverTheme.content:
{
"colorA": "#fff",
"colorB": "#000"
}
###CapRoverTheme.extra:
Additional theme content
###CapRoverTheme.headEmbed:
<meta name="theme-color" content="#ffffff">
Error Handling
If theme operations fail, the system will return an error with one of these messages:
- "Theme not found"
- "Cannot delete a built-in theme"
- "Cannot edit a built-in theme"
- "Wanted to store a new theme, but it already exists with the same name"
Example error response:
{
"status": 1110,
"description": "Cannot delete a built-in theme",
"data": {}
}
Pro Features
Manage API Key
Manages Pro API key.
POST /api/v2/user/pro/apikey/
Description:
Manages the Pro API key configuration.
Authentication: Required - JWT token in x-captain-auth header
OTP Management
Manages OTP settings.
GET /api/v2/user/pro/otp/
POST /api/v2/user/pro/otp/
Description:
Retrieves and configures OTP settings.
Authentication: Required - JWT token in x-captain-auth header
Pro Configurations
Manages Pro feature configurations.
GET /api/v2/user/pro/configs/
POST /api/v2/user/pro/configs/
Description:
Retrieves and updates Pro feature configurations.
Authentication: Required - JWT token in x-captain-auth header
Get Pro State
Retrieves Pro feature state.
GET /api/v2/user/pro/state/
Description:
Retrieves the current state of Pro features.
Authentication: Required - JWT token in x-captain-auth header
Webhooks
Webhook Tokens
Webhook tokens are automatically generated when you configure a Git repository for an app. The token is used to authenticate webhook requests from Git providers.
Getting a Webhook Token
- Configure a Git repository for your app using the app update endpoint:
POST /api/v2/user/apps/appDefinitions/update/
{
"appName": "my-app",
"appPushWebhook": {
"repoInfo": {
"repo": "https://github.com/username/repo.git",
"branch": "main",
"user": "username",
"password": "password-or-token"
}
}
}
- After updating, retrieve your app's configuration to get the webhook token:
GET /api/v2/user/apps/appDefinitions/
Look for appPushWebhook.pushWebhookToken
in the response.
The webhook token is automatically managed by CapRover - you don't need to manually generate or manage it. It's created when you set up Git repository integration for your app.
Trigger Build
Triggers a build via webhook.
POST /api/v2/user/apps/webhooks/triggerbuild
Description:
Triggers a build for an application via webhook. This endpoint supports webhooks from various Git providers (GitHub, GitLab, Bitbucket) and can be used to automatically deploy new versions of your application when code changes are pushed to the repository.
Authentication: Required - Webhook token in query parameters:
token
: The webhook token for the applicationnamespace
: The CapRover namespace
Query Parameters:
?token=<webhook-token>&namespace=<namespace>
Request Headers (Git Provider Specific):
- GitHub:
X-GitHub-Event: push
- GitLab:
X-Gitlab-Event: Push Hook
- Bitbucket:
X-Event-Key: repo:push
andX-Request-UUID
andX-Hook-UUID
Response:
{
"status": 100,
"description": "Build webhook has triggered",
"data": {}
}
Status Codes:
- 100: Success
- 1000: Error - Generic error (if app information cannot be extracted)
Notes:
- The webhook token is generated when repository information is configured for an app
- The token is unique per application and namespace
- The build will only trigger if the pushed branch matches the configured branch
- The build process runs asynchronously
- The response is sent immediately, before the build starts
- Build logs can be monitored using the Get App Logs endpoint
- The webhook supports both form-encoded and JSON payloads
- For GitHub webhooks, the payload can be either in the request body or in a form field named 'payload'
Implementation Details
- Webhooks are processed through a dedicated router (
WebhooksRouter
) - The system supports multiple Git providers:
- GitHub: Detects pushes via
X-GitHub-Event: push
- GitLab: Detects pushes via
X-Gitlab-Event: Push Hook
- Bitbucket: Detects pushes via
X-Event-Key: repo:push
- GitHub: Detects pushes via
- Branch detection:
- GitHub: Extracts branch from
refs/heads/branch-name
- GitLab: Extracts branch from
refs/heads/branch-name
- Bitbucket: Extracts branches from
push.changes[].new.name
- GitHub: Extracts branch from
- The build is only triggered if the pushed branch matches the configured branch
- The build process is scheduled asynchronously to avoid timeout issues
- Build failures are logged but don't affect the webhook response
Error Handling
If the webhook fails, the system will return an error with one of these messages:
- "Error triggering a build"
- "Something went wrong during trigger build. Cannot extract app information from the payload."
Example error response:
{
"status": 1000,
"description": "Error triggering a build",
"data": {}
}
Security Considerations
- Webhook tokens are unique per application and namespace
- Tokens are generated using a secure random UUID
- The token version is stored with the application configuration
- Webhook requests are validated before processing
- The system supports both HTTP and HTTPS webhooks
- Webhook URLs should be kept secure and not shared publicly
Registry Management
Insert Registry
Adds a new registry.
POST /api/v2/user/registries/insert/
Description:
Adds a new Docker registry configuration.
Authentication: Required - JWT token in x-captain-auth header
Update Registry
Updates an existing registry.
POST /api/v2/user/registries/update/
Description:
Updates an existing Docker registry configuration.
Authentication: Required - JWT token in x-captain-auth header
Delete Registry
Deletes a registry.
POST /api/v2/user/registries/delete/
Description:
Deletes a Docker registry configuration.
Authentication: Required - JWT token in x-captain-auth header
Set Push Registry
Sets the default push registry.
POST /api/v2/user/registries/setpush/
Description:
Sets the default registry for pushing Docker images.
Authentication: Required - JWT token in x-captain-auth header
User Management
Change Password
Changes the user's password.
POST /api/v2/user/changepassword/
Description:
Changes the current user's password.
Authentication: Required - JWT token in x-captain-auth header
Download
Download Endpoint
Downloads files from the CapRover instance.
GET /api/v2/download/
Description:
Downloads files from the CapRover instance.
Authentication: Required - JWT token in x-captain-auth header