Skip to main content

Endpoint

POST /v1/validate
Validates a stack configuration without generating files. Performs dependency resolution, conflict detection, port conflict checks, and resource estimation. Use this endpoint to validate user input before calling /v1/generate.

Authentication

X-API-Key
string
Optional API key for authenticated requests with higher rate limits

Request Body

services
array
Array of service IDs to validate (e.g., ["postgresql", "redis", "n8n"])
skillPacks
array
Array of skill pack IDs to validate (e.g., ["devops", "research"])
proxy
string
Reverse proxy to validate: caddy or traefik
domain
string
Base domain for validation (optional)
gpu
boolean
default:"false"
Whether GPU support is enabled
platform
string
Target platform: linux/amd64 or linux/arm64

Response

valid
boolean
required
Whether the configuration is valid and ready for generation
resolvedServices
array
required
Array of all service IDs after dependency resolution (includes auto-added dependencies)
addedDependencies
array
required
Array of services that were automatically added to satisfy dependencies
warnings
array
required
Array of non-fatal warnings (e.g., high memory usage, experimental services)
conflicts
array
required
Array of fatal conflicts that prevent generation (empty if valid)
estimatedMemoryMB
number
required
Total estimated memory usage in megabytes for all resolved services

Examples

Valid Configuration

curl -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -d '{
    "services": ["redis", "n8n"],
    "proxy": "caddy"
  }'
Response (200):
{
  "valid": true,
  "resolvedServices": ["redis", "n8n", "postgresql"],
  "addedDependencies": [
    {
      "service": "postgresql",
      "requiredBy": "n8n",
      "reason": "n8n requires PostgreSQL for data storage"
    }
  ],
  "warnings": [],
  "conflicts": [],
  "estimatedMemoryMB": 896
}
Note that PostgreSQL was automatically added as a dependency of n8n.

Configuration with Warnings

curl -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -d '{
    "services": ["ollama", "stable-diffusion", "open-webui"],
    "gpu": true
  }'
Response (200):
{
  "valid": true,
  "resolvedServices": ["ollama", "stable-diffusion", "open-webui"],
  "addedDependencies": [],
  "warnings": [
    {
      "code": "HIGH_MEMORY",
      "message": "Stack requires ~6.5 GB memory. Ensure sufficient resources.",
      "service": null
    },
    {
      "code": "EXPERIMENTAL_SERVICE",
      "message": "stable-diffusion is experimental and may not be production-ready",
      "service": "stable-diffusion"
    },
    {
      "code": "GPU_REQUIRED",
      "message": "GPU support enabled. Ensure NVIDIA Container Toolkit is installed.",
      "service": null
    }
  ],
  "conflicts": [],
  "estimatedMemoryMB": 6656
}
Configuration is valid but has warnings about resource requirements.

Configuration with Conflicts

curl -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -d '{
    "services": ["redis", "valkey"]
  }'
Response (200):
{
  "valid": false,
  "resolvedServices": ["redis", "valkey"],
  "addedDependencies": [],
  "warnings": [],
  "conflicts": [
    {
      "code": "SERVICE_CONFLICT",
      "message": "redis and valkey cannot be used together: both are Redis-compatible and conflict on port 6379",
      "services": ["redis", "valkey"]
    }
  ],
  "estimatedMemoryMB": 256
}
Configuration is invalid due to conflicting services.

Skill Pack Validation

curl -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -d '{
    "services": [],
    "skillPacks": ["research", "devops"]
  }'
Response (200):
{
  "valid": true,
  "resolvedServices": [
    "qdrant", "searxng", "browserless", "redis",
    "n8n", "postgresql", "uptime-kuma", "grafana", "prometheus"
  ],
  "addedDependencies": [
    {
      "service": "qdrant",
      "requiredBy": "research",
      "reason": "Research skill pack requires vector database"
    },
    {
      "service": "postgresql",
      "requiredBy": "n8n",
      "reason": "n8n requires PostgreSQL for data storage"
    }
    /* ... more dependencies */
  ],
  "warnings": [
    {
      "code": "HIGH_MEMORY",
      "message": "Stack requires ~4.8 GB memory. Ensure sufficient resources.",
      "service": null
    }
  ],
  "conflicts": [],
  "estimatedMemoryMB": 4864
}
Skill packs automatically resolve to their required services.

Empty Configuration

curl -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -d '{
    "services": []
  }'
Response (200):
{
  "valid": true,
  "resolvedServices": [],
  "addedDependencies": [],
  "warnings": [
    {
      "code": "EMPTY_STACK",
      "message": "No services selected. Stack will be empty.",
      "service": null
    }
  ],
  "conflicts": [],
  "estimatedMemoryMB": 0
}

With Authentication

curl -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -H "X-API-Key: sk_live_abc123" \
  -d '{"services": ["redis", "postgresql"]}'

Error Responses

Validation Error (400)

Invalid request body:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request body",
    "details": [
      {
        "field": "services",
        "message": "Expected array, received string"
      }
    ]
  }
}

Internal Error (500)

Unexpected validation failure:
{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Validation failed: unable to resolve dependencies"
  }
}

Unauthorized (401)

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key."
  }
}

Common Warning Codes

CodeDescription
HIGH_MEMORYStack requires significant memory (>4 GB)
EXPERIMENTAL_SERVICEOne or more services are experimental
GPU_REQUIREDGPU support enabled, requires NVIDIA toolkit
EMPTY_STACKNo services selected
PORT_CONFLICT_RESOLVEDPort conflict auto-resolved by reassignment

Common Conflict Codes

CodeDescription
SERVICE_CONFLICTIncompatible services selected
PORT_CONFLICTUnresolvable port conflict
DEPENDENCY_MISSINGRequired dependency unavailable
PLATFORM_INCOMPATIBLEService not available for target platform

Use Cases

Pre-Generation Validation

Validate before generating:
async function createStack(config) {
  // Validate first
  const validation = await fetch('http://localhost:3456/v1/validate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(config)
  }).then(r => r.json());
  
  if (!validation.valid) {
    console.error('Configuration errors:', validation.conflicts);
    return;
  }
  
  if (validation.warnings.length > 0) {
    console.warn('Configuration warnings:', validation.warnings);
  }
  
  // Show added dependencies
  if (validation.addedDependencies.length > 0) {
    console.log('Auto-added services:', 
      validation.addedDependencies.map(d => d.service)
    );
  }
  
  // Proceed with generation
  const result = await fetch('http://localhost:3456/v1/generate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ...config, projectName: 'my-stack' })
  });
}

Interactive Service Picker

Validate as user selects services:
let selectedServices = [];

async function onServiceToggle(serviceId, checked) {
  if (checked) {
    selectedServices.push(serviceId);
  } else {
    selectedServices = selectedServices.filter(s => s !== serviceId);
  }
  
  // Validate on every change
  const validation = await fetch('http://localhost:3456/v1/validate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ services: selectedServices })
  }).then(r => r.json());
  
  // Update UI with dependencies
  displayDependencies(validation.addedDependencies);
  
  // Show conflicts
  if (validation.conflicts.length > 0) {
    showErrors(validation.conflicts);
  }
  
  // Update memory estimate
  updateMemoryDisplay(validation.estimatedMemoryMB);
}

Resource Planning

Estimate resources before deployment:
#!/bin/bash
# Check if server has enough resources

VALIDATION=$(curl -s -X POST http://localhost:3456/v1/validate \
  -H "Content-Type: application/json" \
  -d "$(cat stack-config.json)")

REQUIRED_MB=$(echo $VALIDATION | jq '.estimatedMemoryMB')
AVAILABLE_MB=$(free -m | awk 'NR==2 {print $7}')

if [ $REQUIRED_MB -gt $AVAILABLE_MB ]; then
  echo "Insufficient memory: need ${REQUIRED_MB}MB, have ${AVAILABLE_MB}MB"
  exit 1
fi

echo "Memory check passed. Proceeding with generation..."

Next Steps

Generate Endpoint

Generate stacks after validation passes

Services Endpoint

Explore service dependencies and conflicts

Build docs developers (and LLMs) love