HTTP API¶
The kikx-backend HTTP API, built from backend/. It is stateless, renders only, and never writes to disk. Bind address and port are set in Configuration.
Base URL: http://127.0.0.1:4000 by default. All paths are under /api.
Method |
Path |
Request |
Response |
|---|---|---|---|
|
— |
|
|
|
— |
|
|
|
— |
|
|
|
— |
|
|
|
— |
|
|
|
path |
Preset manifest |
|
|
query |
|
|
|
|
|
GET routes also answer HEAD. Any other method on a known path returns 405 Method Not Allowed with an allow header. An unknown path returns 404 Not Found with an empty body.
GET /api/health¶
Response 200, content-type: text/plain; charset=utf-8:
ok
GET /api/components¶
References of the built-in components, in registry order.
Response 200:
{"components":["k8s/deployment","k8s/service","k8s/ingress","terraform/digitalocean","terraform/hetzner","ansible/k8s-bootstrap","ansible/inventory","ansible/group-vars","ansible/common-role","ansible/role","ansible/playbook","ansible/site","ansible/config"]}
Key |
Type |
|---|---|
|
array of strings |
GET /api/registry¶
Every built-in component.
Response 200:
{"items":[{"name":"deployment","category":"k8s","title":"Deployment","description":"Pods running one container image.","reference":"k8s/deployment","fields":[{"name":"image","required":true,"default":null,"description":null,"example":"nginx:1.27","options":[]},{"name":"replicas","required":false,"default":"1","description":null,"example":null,"options":[]},{"name":"port","required":false,"default":"80","description":null,"example":null,"options":[]}],"files":["{{ name }}-deployment.yaml"]}]}
The example shows the first item only. The full content is listed in Components.
Key |
Type |
|---|---|
|
array of |
RegistryItem¶
Key |
Type |
Description |
|---|---|---|
|
string |
Component name |
|
string |
Component category |
|
string |
Display title, |
|
string |
One-line description, |
|
string |
|
|
array of |
Declared fields, in order |
|
array of strings |
Output path templates, unrendered. Template bodies are not included |
Field¶
Key |
Type |
Description |
|---|---|---|
|
string |
Field name |
|
boolean |
Rendering fails when no value and no default |
|
string or |
Value used when none is supplied |
|
string or |
Help text |
|
string or |
Example value |
|
array of |
Suggested values. |
GET /api/config¶
Project defaults compiled into kikx-core.
Response 200:
{"defaultNamespace":"default","defaultOutputDir":"k8s","defaultProjectName":"kikx-project"}
Key |
Type |
|---|---|
|
string |
|
string |
|
string |
GET /api/presets¶
Summaries of the built-in preset templates, in the order kikx presets prints them.
Response 200:
{"presets":[{"name":"k8s-web-app","title":"Kubernetes web app","description":"A web frontend and an API behind ingresses, plus a background worker.","componentCount":7},{"name":"single-server","title":"Single server with Ansible","description":"One DigitalOcean droplet, configured by a common role through a site playbook.","componentCount":7},{"name":"kubeadm-cluster","title":"Kubernetes cluster with kubeadm","description":"Hetzner servers bootstrapped into a three-node control plane and three workers.","componentCount":11},{"name":"web-and-database","title":"Web servers and a database","description":"Existing servers split into a web tier and a PostgreSQL primary with a replica.","componentCount":13},{"name":"multi-tier-platform","title":"Multi-tier platform","description":"A storefront platform: edge load balancers, web/app tiers, PostgreSQL primary + replicas, Redis, monitoring and a Kubernetes cluster.","componentCount":35}]}
Key |
Type |
|---|---|
|
array of |
PresetSummary¶
Key |
Type |
Description |
|---|---|---|
|
string |
Template name, accepted by |
|
string |
Display title, |
|
string |
One-line description, |
|
integer |
Number of components in the template |
GET /api/presets/{name}¶
Returns one built-in template as a preset manifest, in the Preset format. Every key is present: fields and labels are {} when the template leaves them out, and project.name is null when unset. The dashboard renders each component through POST /api/render to open it.
Path parameter |
Description |
|---|---|
|
Template name, as listed by |
Request:
GET /api/presets/k8s-web-app
Response 200, shortened to the first component:
{"name":"k8s-web-app","title":"Kubernetes web app","description":"A web frontend and an API behind ingresses, plus a background worker.","project":{"name":"web-app","namespace":"web","outputDir":"k8s"},"components":[{"reference":"k8s/deployment","name":"frontend","fields":{"image":"ghcr.io/example/frontend:1.0.0","replicas":"2","port":"3000"},"labels":{}}]}
Condition |
Status |
Body |
|---|---|---|
No template with that name |
|
|
GET /api/registry/inspect¶
Resolves one reference and returns its RegistryItem.
Query parameter |
Required |
Description |
|---|---|---|
|
yes |
Built-in reference, URL, or path to a |
Request:
GET /api/registry/inspect?ref=k8s/service
Response 200:
{"name":"service","category":"k8s","title":"Service","description":"A stable address for pods.","reference":"k8s/service","fields":[{"name":"port","required":false,"default":"80","description":null,"example":null,"options":[]},{"name":"target_port","required":false,"default":null,"description":"Container port; defaults to the service port.","example":null,"options":[]}],"files":["{{ name }}-service.yaml"]}
Condition |
Status |
Body |
|---|---|---|
Unknown reference |
|
|
URL fetch fails |
|
|
File or response is not a registry item |
|
|
|
|
|
POST /api/render¶
Renders one component and returns the file contents. Writes nothing. Path safety checks applied by the CLI when writing are not applied.
Request headers: Content-Type: application/json.
RenderRequest¶
Key |
Type |
Required |
Default |
Description |
|---|---|---|---|---|
|
string |
yes |
— |
Component reference |
|
string |
yes |
— |
|
|
object of string to string |
no |
|
Field values |
|
array of |
no |
|
Labels. |
|
string |
no |
|
Namespace used when no |
|
string |
no |
— |
Sets field |
|
unsigned 32-bit integer |
no |
— |
Sets field |
|
integer |
no |
— |
Sets field |
|
integer |
no |
— |
Sets field |
|
string |
no |
— |
Sets field |
|
string |
no |
— |
Sets field |
|
string |
no |
— |
Sets field |
|
string |
no |
— |
Sets field |
A key in fields wins over the top-level key that sets the same field. Unknown top-level keys are ignored.
Request:
{"reference":"k8s/service","name":"web","port":8080,"labels":[{"key":"tier","value":"frontend"}]}
Response 200:
{"component":"service","files":[{"path":"web-service.yaml","content":"apiVersion: v1\nkind: Service\nmetadata:\n name: web\n namespace: default\nspec:\n selector:\n\n app: web\n\n tier: frontend\n\n ports:\n - port: 8080\n targetPort: 8080\n protocol: TCP\n"}]}
RenderResponse¶
Key |
Type |
Description |
|---|---|---|
|
string |
Component name, without category |
|
array of |
Rendered path, relative, and file content |
Errors¶
Condition |
Status |
Content type |
Body |
|---|---|---|---|
Unknown or invalid reference |
|
JSON |
|
Required field missing |
|
JSON |
|
Two files render to the same path |
|
JSON |
|
Template syntax or render error |
|
JSON |
|
Missing |
|
text |
|
Body is not valid JSON |
|
text |
|
Missing key or wrong type |
|
text |
|
Error shape¶
Errors raised by kikx use this JSON body, with content-type: application/json:
{"code":"invalid_request","error":"--image is required for k8s/deployment"}
|
Status |
|---|---|
|
|
|
|
|
|
|
|
|
|
not_initialized and already_exists are defined but not returned by any current endpoint. Request parsing errors are returned by the framework as text/plain, as listed per endpoint.
CORS¶
Setting |
Value |
|---|---|
Allowed methods |
|
Allowed request headers |
|
Allowed origins, |
Any origin whose host is |
Allowed origins, |
Exactly the listed origins. Loopback origins are no longer allowed unless listed |
An allowed origin is echoed in access-control-allow-origin. A disallowed origin gets no access-control-allow-origin header; the request itself is still processed. Every response carries vary: origin. Preflight OPTIONS requests return 200 with access-control-allow-methods: GET,POST and access-control-allow-headers: content-type.
Preflight for http://localhost:3000:
HTTP/1.1 200 OK
vary: origin
access-control-allow-methods: GET,POST
access-control-allow-headers: content-type
access-control-allow-origin: http://localhost:3000
allow: POST
content-length: 0