Api
API Versioning & Stability Guarantees
This document describes Capacitarr's API versioning policy, what constitutes a breaking change, and what API consumers can rely on remaining stable.
Current API Version
The stable API is v1, served at:
http://localhost:2187/api/v1/
All endpoints documented in the OpenAPI spec are under this prefix.
Semantic Versioning
Capacitarr follows Semantic Versioning (MAJOR.MINOR.PATCH). Here's how semver maps to API changes:
| Version Bump | What Changes |
|---|---|
| PATCH | Bug fixes to existing endpoint behavior, documentation corrections |
| MINOR | New endpoints, new optional query parameters, new fields added to responses, new optional fields in request bodies |
| MAJOR | URL prefix changes (/api/v2/), field removals, field type changes, endpoint removals, breaking changes to auth behavior |
What Is a Breaking Change
The following are considered breaking changes and will only occur in a major version bump:
- Removing a field from a response body
- Changing a field's type (e.g.,
string→number) - Removing an endpoint
- Changing an endpoint's HTTP method
- Making a previously optional request field required
- Changing authentication requirements (e.g., making a public endpoint require auth)
- Changing the error response format (structure, not message text)
What Is NOT a Breaking Change
The following are non-breaking and may occur in any minor or patch release:
- Adding new fields to response bodies
- Adding new endpoints
- Adding new optional query parameters
- Adding new optional fields to request bodies
- Adding new enum values to existing fields (e.g., new integration types)
- Changing error messages (the text, not the structure)
- Performance improvements
Stability Guarantees
API consumers can rely on the following remaining stable within /api/v1/:
- No breaking changes to
/api/v1/endpoints without a major version bump - All three authentication methods — API key header, Bearer JWT, and Cookie JWT — are stable
- Response JSON field names use
camelCaseand will not be renamed - HTTP status codes for success (
200,201) and error (400,401,403,404,409,500) cases are stable - Error response format —
{"error": "message"}— is stable
Deprecation Policy
When an endpoint or field needs to be removed:
- It will be deprecated first with a minimum notice period before removal
- Deprecated endpoints will include a
DeprecationHTTP header in responses - A
/api/v2/version will be introduced before any breaking changes take effect - Both
/api/v1/and/api/v2/will run simultaneously during a transition period to give consumers time to migrate
Recommendations for API Consumers
- Ignore unknown fields in responses — new fields may be added at any time (forward compatibility)
- Don't rely on field ordering in JSON responses
- Use the OpenAPI spec as the source of truth for request/response shapes
- Pin to a specific API version (
/api/v1/) — don't use unversioned endpoints
Breaking Changes in v2.0.0
The 2.0.0 release includes the following breaking changes from the pre-release (1.0.0-rc.x) series:
Database
- Fresh database schema. The 18 incremental migrations have been replaced with a single baseline migration. Existing databases from 1.0.0-rc.x are not compatible — users start fresh on upgrade.
- The
audit_logstable has been split into two purpose-specific tables:approval_queue— active items in the approval workflow (state machine:pending→approved/rejected)audit_log— permanent, append-only history of deletions and dry-runs
API Endpoints
| Old Endpoint | New Endpoint | Notes |
|---|---|---|
GET /api/v1/audit | GET /api/v1/audit-log | History only (deleted, dry-run, dry-delete) |
GET /api/v1/audit/recent | GET /api/v1/audit-log/recent | Dashboard mini-feed (history) |
GET /api/v1/audit/grouped | GET /api/v1/audit-log/grouped | Grouped history view |
POST /api/v1/audit/:id/approve | POST /api/v1/approval-queue/:id/approve | Approve a queued item |
POST /api/v1/audit/:id/reject | POST /api/v1/approval-queue/:id/reject | Reject (snooze) a queued item |
POST /api/v1/audit/:id/unsnooze | POST /api/v1/approval-queue/:id/unsnooze | Requeue a snoozed item |
| (none) | GET /api/v1/approval-queue | List queued items |
| (none) | DELETE /api/v1/approval-queue/:id | Remove a specific queued item |
| (none) | POST /api/v1/approval-queue/clear | Clear all queued items |
| (none) | GET /api/v1/events | SSE real-time event stream |
New v2 Endpoint Groups
| Group | Endpoints | Description |
|---|---|---|
| Analytics | GET /api/v1/analytics/dead-content, stale-content, forecast | Watch intelligence and capacity forecast |
| Factor Weights | GET, PUT /api/v1/scoring-factor-weights | Pluggable scoring factor weight registry |
| Migration | GET /api/v1/migration/status, POST /execute, /dismiss | v1→v2 database migration |
| Deletion Queue | GET, DELETE /api/v1/deletion-queue, POST /snooze, /clear, GET /grace-period | Deletion queue management |
| Settings Backup | GET /api/v1/settings/export, POST /import, /import/preview, /import/commit | Settings export/import with section-level granularity |
Response Schema Changes
AuditLog→AuditLogEntry: removedsnoozedUntilfield,actionrestricted todeleted/dry_run/dry_delete- New
ApprovalQueueItemtype withstatusfield (pending/approved/rejected) instead of overloadedaction PreferenceSet: scoring weight fields (watchHistoryWeight,fileSizeWeight, etc.) moved to separateScoringFactorWeighttable and/scoring-factor-weightsendpointIntegrationConfig: newlibraryIdandcollectionDeletionfields;overseerrtype renamed toseerr- Activity events are now streamed via SSE in addition to the REST endpoint
Architecture
- All business logic moved from route handlers to a service layer
- Event bus replaces direct
LogActivity()calls — 70 typed event types (see Architecture for current count) - SSE replaces polling for real-time UI updates
- Notification dispatch is event-driven (subscriber) instead of inline calls