mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 07:41:27 +00:00
feat(api): error codes, idempotency keys, cursor pagination
- Stable machine-readable error codes alongside the error message (UNAUTHENTICATED, INVALID_TOKEN, ADMIN_REQUIRED, SCOPE_INSUFFICIENT, IDEMPOTENCY_IN_PROGRESS); CLI renders "CODE: message". - Idempotency middleware on authed/admin groups: POST requests with an Idempotency-Key header replay the first response for 24h (Redis-backed, caller-scoped); concurrent duplicates get 409. X-Idempotent-Replay header marks replays. - Shared pagination helpers: ?cursor= (opaque, preferred) alongside legacy ?page= on projects and deployments lists; pagination meta includes next_cursor; invalid cursors fail soft to page 1. - CLI --idempotency-key flag for safe scripted retries. - OpenAPI updated: error envelope, cursor params, idempotency contract. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
485e41a817
commit
18f78f00a3
15 files changed
+454
-56
No files matched your search
+44
-5
@@ -8,10 +8,27 @@ info:
|
||||
Containr provides a comprehensive platform for deploying, managing, and scaling containerized applications on Proxmox infrastructure. This API allows you to manage projects, services, deployments, databases, and more through a RESTful interface.
|
||||
|
||||
## Authentication
|
||||
The API uses JWT-based authentication. Include your JWT token in the Authorization header:
|
||||
```
|
||||
Authorization: Bearer <your-jwt-token>
|
||||
```
|
||||
The API accepts three credentials in the Authorization header:
|
||||
`Authorization: Bearer <jwt>` (UI sessions), a Better Auth session cookie, or a
|
||||
personal access token `cnp_...` (CLI/MCP/agents). PAT scopes: `read` allows only
|
||||
GET/HEAD/OPTIONS; `write` everything except admin routes; `admin` requires a
|
||||
platform-admin owner.
|
||||
|
||||
## Errors
|
||||
Error responses use `{"error": "human message", "code": "MACHINE_CODE"}`. Stable
|
||||
codes: `UNAUTHENTICATED`, `INVALID_TOKEN`, `FORBIDDEN`, `ADMIN_REQUIRED`,
|
||||
`SCOPE_INSUFFICIENT`, `NOT_FOUND`, `VALIDATION`, `CONFLICT`, `INTERNAL`,
|
||||
`DEPENDENCY_UNAVAILABLE`, `IDEMPOTENCY_IN_PROGRESS`.
|
||||
|
||||
## Idempotency
|
||||
POST endpoints accept an `Idempotency-Key` header. The first response is replayed
|
||||
for repeated keys within 24h (scoped to the caller and path); a concurrent duplicate
|
||||
receives `409 IDEMPOTENCY_IN_PROGRESS`. Safe for clients to always send a UUID.
|
||||
|
||||
## Pagination
|
||||
List endpoints accept `?limit=` plus either `?page=` (legacy) or `?cursor=`
|
||||
(preferred — pass `pagination.next_cursor` from the previous response verbatim).
|
||||
Invalid cursors fail soft to the first page.
|
||||
|
||||
## Base URL
|
||||
```
|
||||
@@ -255,7 +272,7 @@ paths:
|
||||
parameters:
|
||||
- name: page
|
||||
in: query
|
||||
description: Page number for pagination
|
||||
description: Page number for pagination (legacy — prefer cursor)
|
||||
schema:
|
||||
type: integer
|
||||
default: 1
|
||||
@@ -265,6 +282,11 @@ paths:
|
||||
schema:
|
||||
type: integer
|
||||
default: 20
|
||||
- name: cursor
|
||||
in: query
|
||||
description: Opaque cursor from a previous response's pagination.next_cursor
|
||||
schema:
|
||||
type: string
|
||||
- name: search
|
||||
in: query
|
||||
description: Search term to filter projects
|
||||
@@ -660,6 +682,17 @@ paths:
|
||||
description: Service ID
|
||||
schema:
|
||||
type: string
|
||||
- name: limit
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
default: 50
|
||||
maximum: 100
|
||||
- name: cursor
|
||||
in: query
|
||||
description: Opaque cursor from a previous response's pagination.next_cursor
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Deployments retrieved successfully
|
||||
@@ -712,6 +745,12 @@ paths:
|
||||
type: integer
|
||||
default: 10
|
||||
maximum: 50
|
||||
- name: cursor
|
||||
in: query
|
||||
required: false
|
||||
description: Opaque cursor from a previous response's pagination.next_cursor
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Recent deployments
|
||||
|
||||
Reference in new issue
Block a user