Skip to content

Storage policies and retention ​

Quotas, usage, retention policies, their preview and run, cleanup and deletion of artifacts.

Operations of this group with their access rule, retry rule, parameters and answers. Every request carries a key: Authorization: Bearer <key> (see Authentication).

Operations ​

Check whether an artifact can be deleted ​

GET HEAD /api/v1/repositories/{repository}/artifacts/{id}/deletion

Access: Repository permission: artifact.delete · Retry: Safe to repeat (read)

Returns the artifact's name, size, publication time, current annotationRevision and the blockers that would keep it from deletion: reference (an external reference, or use by a container image, Git LFS or npm), asset_history (a current or earlier file path revision), attachment_history or promotion_stage. Nothing changes; pass the revision to deleteArtifact as expectedAnnotationRevision.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$
idpathstring (uuid)yes—

Response 200

FieldTypeRequiredRules
idstring (uuid)yes—
namestringyes1–240 characters
sizestringyesa whole number in decimal digits, sent as a string
publishedAtstring (date-time)yes—
annotationRevisionintegeryes0–2147483647
blockersarray of stringyesup to 4 items; no repeated items; each: one of reference, asset_history, attachment_history, protected_label, promotion_stage

Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507

Example

bash
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/artifacts/$ID/deletion" \
  -H "Authorization: Bearer $ARKVORY_TOKEN"

Preview retention candidates ​

POST /api/v1/repositories/{repository}/retention/preview

Access: Repository permission: artifact.delete · Retry: Safe to repeat (read)

Lists the published artifacts released before criteria.publishedBefore (a past UTC time with milliseconds), ordered by ID, each with its annotation revision and blockers, protected_label meaning one of criteria.protectedLabels (an explicit list of up to 32). Pages hold limit items (1–100, default 50); continue with after set to next. Nothing is reserved: choose the items to delete and pass them with their revisions to applyRetention, which checks them again.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Request body (application/json)

FieldTypeRequiredRules
criteriaobjectyes—
criteria.publishedBeforestring (date-time)yesmatches ^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$
criteria.protectedLabelsarray of stringyesup to 32 items; no repeated items; each: 1–64 characters
limitintegerno1–100
afterstring (uuid)no—

Response 200

FieldTypeRequiredRules
itemsarray of objectyesup to 100 items
items[].idstring (uuid)yes—
items[].namestringyes1–240 characters
items[].sizestringyesa whole number in decimal digits, sent as a string
items[].publishedAtstring (date-time)yes—
items[].annotationRevisionintegeryes0–2147483647
items[].blockersarray of stringyesup to 4 items; no repeated items; each: one of reference, asset_history, attachment_history, protected_label, promotion_stage
nextstring (uuid)yesmay be null

Responses: 200, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507

Example

bash
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/retention/preview" \
  -H "Authorization: Bearer $ARKVORY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"criteria":{"publishedBefore":"2026-01-01T00:00:00.000Z","protectedLabels":[]}}'

Delete the selected retention candidates ​

POST /api/v1/repositories/{repository}/retention/apply

Access: Repository permission: artifact.delete · Retry: Safe to repeat: the same request has the same effect

Rechecks 1–100 artifacts chosen from previewRetention (items with id and expectedAnnotationRevision) against the same criteria and logically deletes the eligible ones in one transaction. Each item gets an outcome: deleted, already_deleted, changed (the annotations changed), not_eligible (published too late), protected with its blockers, or not_found. The bytes stay reserved until the repository's online cleanup reclaims them.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Request body (application/json)

FieldTypeRequiredRules
criteriaobjectyes—
criteria.publishedBeforestring (date-time)yesmatches ^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z$
criteria.protectedLabelsarray of stringyesup to 32 items; no repeated items; each: 1–64 characters
itemsarray of objectyes1–100 items
items[].idstring (uuid)yes—
items[].expectedAnnotationRevisionintegeryes0–2147483647

Response 200

FieldTypeRequiredRules
itemsarray of objectyes1–100 items
items[].idstring (uuid)yes—
items[].outcomestringyesone of deleted, already_deleted, protected, changed, not_eligible, not_found
items[].blockersarray of stringyesup to 4 items; no repeated items; each: one of reference, asset_history, attachment_history, protected_label, promotion_stage

Responses: 200, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507

Example

bash
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/retention/apply" \
  -H "Authorization: Bearer $ARKVORY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"criteria":{"publishedBefore":"2026-01-01T00:00:00.000Z","protectedLabels":[]},"items":[{"id":"00000000-0000-4000-8000-000000000000","expectedAnnotationRevision":0}]}'

Get the storage policy ​

GET HEAD /api/v1/repositories/{repository}/storage/policy

Access: Repository permission: storage.read · Retry: Safe to repeat (read)

Returns the repository's automatic cleanup and quota settings with their revision, the next and last scheduled run, how many builds the last run deleted and its error. By default the policy is disabled and there is no repository quota (the server-wide capacity still applies).

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Response 200

FieldTypeRequiredRules
revisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.groupingstringyesone of package-channel, package, repository
policy.keepLastintegeryes1–100000
policy.channelsarray of objectyesup to 32 items
policy.channels[].labelstringyes1–64 characters
policy.channels[].keepLastintegeryes1–100000
policy.protectedLabelsarray of stringyesup to 32 items; no repeated items; each: 1–64 characters
policy.minAgeHoursintegeryes0–87600
policy.intervalMinutesintegeryes1–10080
policy.quotaBytesstringyesa whole number in decimal digits, sent as a string; may be null
policy.warningPercentintegeryes1–98
policy.criticalPercentintegeryes2–99
nextRunAtstring (date-time)yesmay be null
lastRunAtstring (date-time)yesmay be null
lastDeletedintegeryes0–100
lastErrorstringyesup to 64 characters; may be null

Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507

Example

bash
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/policy" \
  -H "Authorization: Bearer $ARKVORY_TOKEN"

Replace the storage policy ​

PUT /api/v1/repositories/{repository}/storage/policy

Access: Repository permission: storage.manage · Retry: Repeat only with the expected revision (compare-and-swap)

Replaces the whole policy: keep the last keepLast registered UPack builds per package, per channel label (channels) or per repository (grouping), never delete protectedLabels or builds younger than minAgeHours, run every intervalMinutes, and limit the repository with quotaBytes (a decimal string, null for none) and its warning thresholds. expectedRevision must be the current revision, otherwise 409 revision_mismatch. Enabling also needs artifact.delete and ties the schedule to the calling managed key: once that key is revoked, expires or loses these permissions, scheduled deletion stops until the policy is saved with another key. Ordinary files count against the quota but are never deleted by it.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Request body (application/json)

FieldTypeRequiredRules
expectedRevisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.groupingstringyesone of package-channel, package, repository
policy.keepLastintegeryes1–100000
policy.channelsarray of objectyesup to 32 items
policy.channels[].labelstringyes1–64 characters
policy.channels[].keepLastintegeryes1–100000
policy.protectedLabelsarray of stringyesup to 32 items; no repeated items; each: 1–64 characters
policy.minAgeHoursintegeryes0–87600
policy.intervalMinutesintegeryes1–10080
policy.quotaBytesstringyesa whole number in decimal digits, sent as a string; may be null
policy.warningPercentintegeryes1–98
policy.criticalPercentintegeryes2–99

Response 200

FieldTypeRequiredRules
revisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.groupingstringyesone of package-channel, package, repository
policy.keepLastintegeryes1–100000
policy.channelsarray of objectyesup to 32 items
policy.channels[].labelstringyes1–64 characters
policy.channels[].keepLastintegeryes1–100000
policy.protectedLabelsarray of stringyesup to 32 items; no repeated items; each: 1–64 characters
policy.minAgeHoursintegeryes0–87600
policy.intervalMinutesintegeryes1–10080
policy.quotaBytesstringyesa whole number in decimal digits, sent as a string; may be null
policy.warningPercentintegeryes1–98
policy.criticalPercentintegeryes2–99
nextRunAtstring (date-time)yesmay be null
lastRunAtstring (date-time)yesmay be null
lastDeletedintegeryes0–100
lastErrorstringyesup to 64 characters; may be null

Responses: 200, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507

Example

bash
curl -X PUT "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/policy" \
  -H "Authorization: Bearer $ARKVORY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":0,"policy":{"enabled":false,"grouping":"package-channel","keepLast":1,"channels":[],"protectedLabels":[],"minAgeHours":0,"intervalMinutes":1,"quotaBytes":"1024","warningPercent":1,"criticalPercent":2}}'

Get the storage usage of a repository ​

GET HEAD /api/v1/repositories/{repository}/storage/usage

Access: Repository permission: storage.read · Retry: Safe to repeat (read)

Returns the bytes reserved by the repository as decimal strings: published, pending uploads and retired (deleted or cancelled, not yet reclaimed), their sum reservedBytes, the quota and a state (unlimited, normal, warning, critical, exceeded). This is the logical reservation counted against the quota, not the space used on disk.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Response 200

FieldTypeRequiredRules
publishedBytesstringyesa whole number in decimal digits, sent as a string
pendingBytesstringyesa whole number in decimal digits, sent as a string
retiredBytesstringyesa whole number in decimal digits, sent as a string
reservedBytesstringyesa whole number in decimal digits, sent as a string
quotaBytesstringyesa whole number in decimal digits, sent as a string; may be null
statestringyesone of unlimited, normal, warning, critical, exceeded

Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507

Example

bash
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/usage" \
  -H "Authorization: Bearer $ARKVORY_TOKEN"

Preview what the storage policy would delete ​

GET HEAD /api/v1/repositories/{repository}/storage/preview

Access: Repository permission: artifact.delete · Retry: Safe to repeat (read)

Returns up to 100 registered builds the saved policy would delete now (even while it is disabled), with the policy revision and hasMore; builds kept by references, file paths, attachments, protected labels or age are left out. Nothing is reserved: a run ranks the builds again.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Response 200

FieldTypeRequiredRules
revisionintegeryes0–2147483647
itemsarray of objectyesup to 100 items
items[].idstring (uuid)yes—
items[].namestringyesup to 240 characters
items[].sizestringyesa whole number in decimal digits, sent as a string
items[].publishedAtstring (date-time)yes—
items[].annotationRevisionintegeryes0–2147483647
items[].blockersarray of stringyesup to 0 items
hasMorebooleanyes—

Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507

Example

bash
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/preview" \
  -H "Authorization: Bearer $ARKVORY_TOKEN"

Run the storage policy now ​

POST /api/v1/repositories/{repository}/storage/run

Access: Repository permission: storage.manage, artifact.delete · Retry: Do not repeat automatically

Runs one batch of the enabled policy at once instead of waiting for the schedule: it ranks the builds again, checks permissions and dependencies, and logically deletes up to 100, returning an outcome for each. expectedRevision must be the current policy revision and the policy must be enabled, otherwise 409. The bytes are reclaimed later by the repository's online cleanup, which has its own policy (setCleanup).

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Request body (application/json)

FieldTypeRequiredRules
expectedRevisionintegeryes0–2147483647

Response 200

FieldTypeRequiredRules
itemsarray of objectyesup to 100 items
items[].idstring (uuid)yes—
items[].outcomestringyesone of deleted, already_deleted, protected, changed, not_eligible, not_found
items[].blockersarray of stringyesup to 4 items; each: one of reference, asset_history, attachment_history, protected_label, promotion_stage

Responses: 200, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507

Example

bash
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/run" \
  -H "Authorization: Bearer $ARKVORY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":0}'

List the storage events of a repository ​

GET HEAD /api/v1/repositories/{repository}/storage/events

Access: Repository permission: diagnostics.read · Retry: Safe to repeat (read)

Returns up to 100 diagnostic events of storage policies, quotas, retention and cleanup after the sequence after (default 0), oldest first, each with level, code and a few details; level (info, warning, error) filters them, continue with after set to next. Only the newest 1000 events per repository and 20 000 overall are kept, so export them for longer retention.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$
afterquerystringnoa whole number in decimal digits, sent as a string
levelquerystringnoone of info, warning, error

Response 200

FieldTypeRequiredRules
itemsarray of objectyesup to 100 items
items[].sequencestringyesa whole number in decimal digits, sent as a string
items[].occurredAtstring (date-time)yes—
items[].levelstringyesone of info, warning, error
items[].codestringyesup to 96 characters
items[].detailsmap of string | integeryesup to 16 entries
nextstringyesa whole number in decimal digits, sent as a string; may be null

Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507

Example

bash
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/events" \
  -H "Authorization: Bearer $ARKVORY_TOKEN"

Get the online cleanup settings ​

GET HEAD /api/v1/repositories/{repository}/storage/cleanup

Access: Repository permission: storage.read · Retry: Safe to repeat (read)

Returns the repository's online cleanup policy with its revision (enabled, graceHours, batchSize, intervalSeconds, delayMilliseconds), the last and next run, and how many objects the last batch reclaimed, deferred or failed with the bytes freed. Cleanup is what physically removes cancelled uploads and deleted artifacts; it is off by default.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Response 200

FieldTypeRequiredRules
revisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.graceHoursintegeryes0–8760
policy.batchSizeintegeryes1–100
policy.intervalSecondsintegeryes5–86400
policy.delayMillisecondsintegeryes0–1000
lastRunAtstring (date-time)yesmay be null
nextRunAtstring (date-time)yesmay be null
lastCollectedintegeryes0–100
lastDeferredintegeryes0–100
lastFailedintegeryes0–100
lastReclaimedBytesstringyesa whole number in decimal digits, sent as a string
lastErrorstringyesmay be null

Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507

Example

bash
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/cleanup" \
  -H "Authorization: Bearer $ARKVORY_TOKEN"

Configure online cleanup ​

PUT /api/v1/repositories/{repository}/storage/cleanup

Access: Repository permission: storage.manage · Retry: Repeat only with the expected revision (compare-and-swap)

Replaces the cleanup policy while the server runs: enabled (also to pause), graceHours (0–8760, how long deleted content stays before removal), batchSize (1–100 objects), intervalSeconds (5–86400) and delayMilliseconds (0–1000 between objects). expectedRevision must be the current revision (0 before the first change), otherwise 409 revision_mismatch. A change takes effect between objects, never halfway through one.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Request body (application/json)

FieldTypeRequiredRules
expectedRevisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.graceHoursintegeryes0–8760
policy.batchSizeintegeryes1–100
policy.intervalSecondsintegeryes5–86400
policy.delayMillisecondsintegeryes0–1000

Response 200

FieldTypeRequiredRules
revisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.graceHoursintegeryes0–8760
policy.batchSizeintegeryes1–100
policy.intervalSecondsintegeryes5–86400
policy.delayMillisecondsintegeryes0–1000
lastRunAtstring (date-time)yesmay be null
nextRunAtstring (date-time)yesmay be null
lastCollectedintegeryes0–100
lastDeferredintegeryes0–100
lastFailedintegeryes0–100
lastReclaimedBytesstringyesa whole number in decimal digits, sent as a string
lastErrorstringyesmay be null

Responses: 200, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507

Example

bash
curl -X PUT "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/cleanup" \
  -H "Authorization: Bearer $ARKVORY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":0,"policy":{"enabled":false,"graceHours":0,"batchSize":1,"intervalSeconds":5,"delayMilliseconds":0}}'

Request a cleanup batch now ​

POST /api/v1/repositories/{repository}/storage/cleanup/run

Access: Repository permission: storage.manage · Retry: Do not repeat automatically

Schedules the next batch of the enabled cleanup policy to start at once; the answer is the cleanup state, and the bytes are freed only when the batch has run (see lastRunAt in getCleanup). expectedRevision must be the current revision; a disabled cleanup is a 409 state_conflict. Objects that are being read or written are deferred to a later batch.

Parameters

NameInTypeRequiredRules
repositorypathstringyesmatches ^[a-z0-9][a-z0-9_-]{0,63}$

Request body (application/json)

FieldTypeRequiredRules
expectedRevisionintegeryes0–2147483647

Response 200

FieldTypeRequiredRules
revisionintegeryes0–2147483647
policyobjectyes—
policy.enabledbooleanyes—
policy.graceHoursintegeryes0–8760
policy.batchSizeintegeryes1–100
policy.intervalSecondsintegeryes5–86400
policy.delayMillisecondsintegeryes0–1000
lastRunAtstring (date-time)yesmay be null
nextRunAtstring (date-time)yesmay be null
lastCollectedintegeryes0–100
lastDeferredintegeryes0–100
lastFailedintegeryes0–100
lastReclaimedBytesstringyesa whole number in decimal digits, sent as a string
lastErrorstringyesmay be null

Responses: 200, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507

Example

bash
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/storage/cleanup/run" \
  -H "Authorization: Bearer $ARKVORY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expectedRevision":0}'

Arkvory · ProAnimaStudio