System
Health checks, error codes, rate limits, and deprecation notices.
Health Check
GET /health
Check the overall health status of the Peako API. No authentication required.
Response (Healthy):
{
"status": "ok",
"qsv": true,
"redis": true,
"workers": 4,
"queued": 2,
"uptime": 3600
}
Response (Degraded):
{
"status": "degraded",
"qsv": false,
"redis": true,
"workers": 0,
"queued": 5,
"uptime": 3600,
"error": "QSV hardware encoder unavailable"
}
Fields:
| Field | Type | Description |
|---|---|---|
status | string | "ok" or "degraded" |
qsv | boolean | Intel Quick Sync Video hardware encoder available |
redis | boolean | Redis (job queue) connection healthy |
workers | number | Currently active render workers |
queued | number | Jobs waiting or actively processing |
uptime | number | Server uptime in seconds |
error | string | (degraded only) Reason for degraded status |
Status Codes:
200— All systems operational503— One or more systems degraded
Example:
curl https://peako.shin0x.space/health
Error Codes
All API errors return a consistent JSON body:
{
"statusCode": 400,
"code": "INVALID_REQUEST",
"message": "Field 'blockId' is required"
}
HTTP Status Codes:
| Code | Meaning |
|---|---|
200 | Success |
201 | Created |
202 | Accepted (async job queued) |
400 | Bad request — validation error, invalid params |
401 | Unauthorized — missing or invalid API key / session |
403 | Forbidden — not the owner of this resource |
404 | Not found — resource doesn't exist |
409 | Conflict — queue full, can't cancel active job, etc. |
413 | Payload too large — file exceeds size limit |
429 | Too many requests — rate limited |
500 | Internal server error |
503 | Service unavailable — Redis or render workers down |
Common Error Codes:
| Code | HTTP | Description |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid credentials |
INVALID_REQUEST | 400 | Malformed request body or invalid field values |
NOT_FOUND | 404 | Template, job, or asset not found |
BLOCK_NOT_FOUND | 400 | blockId in render request doesn't exist in template |
REQUIRED_BLOCK_MISSING | 400 | A required block was not filled |
BLOCK_TYPE_MISMATCH | 400 | Fill type doesn't match block type |
CDN_URL_NOT_ALLOWED | 400 | src_url is not from the Peako CDN |
TRANSCRIBE_SOURCE_MISSING | 400 | transcribe_from block is not filled |
QUEUE_DEPTH_EXCEEDED | 409 | User has 20+ active jobs |
FILE_TOO_LARGE | 413 | File exceeds 2 GB limit |
RENDER_FAILED | 500 | Video render error |
INTERNAL_ERROR | 500 | Unexpected server error |
Rate Limits
Per-user limits:
| Limit | Value |
|---|---|
| Concurrent render jobs | 20 max per user |
| File upload size | 2 GB per file |
| Subtitle file size | 1 MB |
| Job result retention | 7 days after completion |
No per-second rate limit — quota is enforced at the job queue level.
If you hit the concurrent job limit (409), wait for pending jobs to complete before submitting new ones.
Deprecated Routes
Old /api/v1/ routes are still functional but deprecated. They will be removed on 2026-07-01.
| Deprecated | Current |
|---|---|
POST /api/v1/trim | POST /api/trim |
POST /api/v1/merge | POST /api/merge |
POST /api/v1/mute | POST /api/mute |
POST /api/v1/add-audio | POST /api/add-audio |
POST /api/v1/subtitle | POST /api/subtitle |
POST /api/v1/blur | POST /api/blur |
POST /api/v1/speed-ramp | POST /api/speed-ramp |
GET /api/v1/templates | GET /api/templates |
POST /api/v1/templates | POST /api/templates |
Deprecated routes respond with a warning header:
Deprecation: true
Sunset: Sat, 01 Jul 2026 00:00:00 GMT
Migrate to the current routes before the sunset date.
Best Practices
- Always check
/healthbefore running batch jobs — verify workers are available - Use
delivery: "async"for anything longer than a few seconds - Upload once, reference many times — upload assets once, reuse the CDN URL across multiple renders
- Pre-transcribe when you can — if you'll reuse captions, transcribe separately and cache the result
- Implement exponential backoff when polling — start at 2s, back off to 30s for longer jobs
- Handle
409gracefully — check job count before submitting, or implement a queue with retry logic - Store output URLs — download rendered videos before the 7-day expiry