mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 20:00:08 +00:00
ed553f1f19
Updates the backend listen port, Vite dev proxy target, Docker EXPOSE, compose port mapping, .env.example default, GitHub Actions smoke-test default, healthcheck URLs, and every doc/example reference. Test fixtures that include example URLs were updated for consistency, though their assertions are port-agnostic. The rate-limit value of 3000 in middleware/rateLimiters.ts and the 3000 entry in WEB_UI_PORTS (which detects user containers like Grafana) are intentionally untouched.
208 lines
6.3 KiB
Plaintext
208 lines
6.3 KiB
Plaintext
---
|
|
title: API Overview
|
|
description: Authenticate, route requests to nodes, and integrate Sencho into your CI/CD pipelines.
|
|
---
|
|
|
|
Sencho exposes a REST API for automating stack deployments, managing webhooks, monitoring fleet health, and integrating with CI/CD pipelines. Since Sencho is self-hosted, the API base URL is your own instance.
|
|
|
|
## Base URL
|
|
|
|
```
|
|
https://your-sencho-instance:1852/api
|
|
```
|
|
|
|
Replace with your actual Sencho host and port. All API paths are prefixed with `/api`.
|
|
|
|
## Authentication
|
|
|
|
Authenticated endpoints require a **Bearer token** in the `Authorization` header. Generate API tokens from **Settings > API Tokens** in the Sencho dashboard.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
|
|
https://your-sencho-instance:1852/api/stacks
|
|
```
|
|
|
|
<Note>
|
|
API Tokens require a Sencho **Admiral** license. Community and Skipper editions do not include this feature.
|
|
</Note>
|
|
|
|
### Token scopes
|
|
|
|
Every token is created with one of three permission levels:
|
|
|
|
| Scope | Allowed actions |
|
|
|-------|----------------|
|
|
| **Read Only** | `GET` requests only — view stacks, containers, and fleet status |
|
|
| **Deploy Only** | Everything in Read Only, plus stack operations: deploy, down, restart, stop, start, update |
|
|
| **Full Admin** | Full stack, container, and node management — all read and write operations |
|
|
|
|
Regardless of scope, all API tokens are blocked from managing other tokens, users, licenses, and SSO configuration.
|
|
|
|
## Node routing
|
|
|
|
Sencho manages multiple nodes (local and remote). To target a specific node, include one of:
|
|
|
|
- **Header:** `x-node-id: 1`
|
|
- **Query parameter:** `?nodeId=1`
|
|
|
|
If omitted, the request targets the default node.
|
|
|
|
```bash
|
|
# Target node ID 2
|
|
curl -H "Authorization: Bearer TOKEN" \
|
|
-H "x-node-id: 2" \
|
|
https://your-sencho-instance:1852/api/stacks
|
|
```
|
|
|
|
## Error format
|
|
|
|
All error responses follow the same shape:
|
|
|
|
```json
|
|
{
|
|
"error": "Human-readable error message",
|
|
"code": "MACHINE_READABLE_CODE"
|
|
}
|
|
```
|
|
|
|
The `code` field is present for specific error types:
|
|
|
|
| Code | Meaning |
|
|
|------|---------|
|
|
| `PAID_REQUIRED` | Endpoint requires a Skipper or Admiral license |
|
|
| `ADMIRAL_REQUIRED` | Endpoint requires an Admiral license |
|
|
| `SCOPE_DENIED` | API token scope does not allow this operation |
|
|
|
|
## Input validation
|
|
|
|
All endpoints that accept a `stackName` path parameter validate it against the pattern `^[a-zA-Z0-9_-]+$`. Stack names may only contain **alphanumeric characters, hyphens, and underscores**. Requests with invalid stack names are rejected immediately:
|
|
|
|
```json
|
|
// 400 Bad Request
|
|
{
|
|
"error": "Invalid stack name"
|
|
}
|
|
```
|
|
|
|
This applies to all stack endpoints: read, write, deploy, down, restart, stop, start, update, rollback, backup, delete, and container listing.
|
|
|
|
## Rate limiting
|
|
|
|
Sencho uses a tiered rate limiting system that balances security with usability:
|
|
|
|
| Tier | Limit | Applies to | Keyed by |
|
|
|------|-------|------------|----------|
|
|
| **Polling** | 300/min | Dashboard status endpoints (`/stats`, `/system/stats`, `/stacks/statuses`, etc.) | User session |
|
|
| **Standard** | 200/min | All other API endpoints | User session |
|
|
| **Webhooks** | 500/min | `POST /webhooks/:id/trigger` | IP address |
|
|
| **Auth** | 5-10/15min | Login, setup, SSO endpoints | IP address |
|
|
|
|
Authenticated requests (browser sessions and API tokens) are rate-limited per user, not per IP. This prevents teams behind shared NAT or VPN from pooling rate limit budgets. Unauthenticated requests fall back to IP-based limiting.
|
|
|
|
Internal node-to-node traffic (requests authenticated with node proxy tokens) bypasses rate limiting entirely.
|
|
|
|
When exceeded, the server responds with `429 Too Many Requests`:
|
|
|
|
```json
|
|
{
|
|
"error": "Too many requests. Please try again shortly."
|
|
}
|
|
```
|
|
|
|
Standard rate limit headers (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`) are included in all API responses, so clients can self-throttle accordingly.
|
|
|
|
The default limits can be tuned via environment variables (`API_RATE_LIMIT`, `API_POLLING_RATE_LIMIT`). See [Self-Hosting](/operations/self-hosting) for details.
|
|
|
|
## License tier requirements
|
|
|
|
Some endpoints are gated by license tier:
|
|
|
|
| Tier | Gated features |
|
|
|------|---------------|
|
|
| **Skipper+** | Webhooks, Fleet snapshots, Stack rollback |
|
|
| **Admiral** | API Tokens, Scheduled Tasks |
|
|
|
|
Requests to gated endpoints on a lower tier return `403` with the appropriate error code.
|
|
|
|
## WebSocket endpoints
|
|
|
|
Sencho also provides real-time streaming via WebSocket connections. These are not part of the OpenAPI spec (OpenAPI does not support WebSocket protocols) but are documented here for completeness.
|
|
|
|
### Stack log streaming
|
|
|
|
Stream live logs from a stack's containers.
|
|
|
|
**URL:** `wss://your-sencho-instance:1852/api/stacks/{stackName}/logs?nodeId={nodeId}`
|
|
|
|
**Authentication:** Pass the token as a cookie (`sencho_token`) or Bearer token. For WebSocket connections, authentication is verified during the upgrade handshake.
|
|
|
|
<CodeGroup>
|
|
|
|
```javascript Node.js
|
|
import WebSocket from "ws";
|
|
|
|
const ws = new WebSocket(
|
|
"wss://your-sencho-instance:1852/api/stacks/my-app/logs",
|
|
{ headers: { Cookie: "sencho_token=YOUR_JWT" } }
|
|
);
|
|
|
|
ws.on("message", (data) => {
|
|
console.log(data.toString());
|
|
});
|
|
```
|
|
|
|
```bash cURL (upgrade check)
|
|
curl -i -N \
|
|
-H "Connection: Upgrade" \
|
|
-H "Upgrade: websocket" \
|
|
-H "Cookie: sencho_token=YOUR_JWT" \
|
|
https://your-sencho-instance:1852/api/stacks/my-app/logs
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
### Container exec
|
|
|
|
Open an interactive shell session inside a running container.
|
|
|
|
**URL:** `wss://your-sencho-instance:1852/ws`
|
|
|
|
**Authentication:** Cookie-based JWT only. API tokens with `read-only` or `deploy-only` scope are blocked.
|
|
|
|
<CodeGroup>
|
|
|
|
```javascript Node.js
|
|
import WebSocket from "ws";
|
|
|
|
const ws = new WebSocket("wss://your-sencho-instance:1852/ws", {
|
|
headers: { Cookie: "sencho_token=YOUR_JWT" },
|
|
});
|
|
|
|
ws.on("open", () => {
|
|
// Initiate exec session
|
|
ws.send(
|
|
JSON.stringify({
|
|
action: "execContainer",
|
|
containerId: "abc123...",
|
|
})
|
|
);
|
|
});
|
|
|
|
ws.on("message", (data) => {
|
|
// Terminal output
|
|
process.stdout.write(data.toString());
|
|
});
|
|
|
|
// Send terminal input
|
|
ws.send(JSON.stringify({ type: "input", data: "ls -la\n" }));
|
|
|
|
// Resize terminal
|
|
ws.send(JSON.stringify({ type: "resize", cols: 120, rows: 40 }));
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
<Warning>
|
|
Container exec requires an **admin** role. API tokens with `read-only` or `deploy-only` scope are blocked, as are node proxy tokens.
|
|
</Warning>
|