Uploads
Resumable uploads: create an upload session, send the bytes whole or in parts, complete it, and follow its completion job.
Operations of this group with their access rule, retry rule, parameters and answers. Every request carries a key: Authorization: Bearer <key> (see Authentication).
Operations
List the received parts of an upload
GET HEAD /api/v1/repositories/{repository}/uploads/{id}/parts
Access: Repository permission: upload.read; file keys: write · Retry: Safe to repeat (read)
Returns partBytes, the part size fixed for this upload when it was created (8 MiB, doubled for files that would need more than 10 000 parts; only the last part is shorter), and the parts already stored with their index, size and SHA-256. Read it before resuming an interrupted multipart upload and send only the missing parts with putUploadPart. Only the upload's creator sees it; for anyone else it is a 404.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
Response 200
| Field | Type | Required | Rules |
|---|---|---|---|
partBytes | integer | no | 8388608–1073741824; Every part has this size except the last one. |
items | array of object | no | — |
items[].index | integer | yes | 0–9999 |
items[].size | integer | yes | 1–1073741824 |
items[].sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507
Example
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID/parts" \
-H "Authorization: Bearer $ARKVORY_TOKEN"Upload one part
PUT /api/v1/repositories/{repository}/uploads/{id}/parts/{index}
Access: Repository permission: upload.write; file keys: write · Retry: Re-read the upload, then decide
Stores the body as part index (from 0) of a pending multipart upload; its length must be exactly partBytes (from listUploadParts), or the remainder for the last part, and X-Content-SHA256 must be the lowercase hex SHA-256 of these bytes, otherwise 422. Parts may arrive in any order, but an upload takes one request at a time (a concurrent one gets 503 busy); sending a part again with the same hash is safe, a different hash for an index already stored is a 409 part_mismatch. When every part is stored, call completeUpload or enqueueCompletion.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
index | path | integer | yes | 0–9999 |
X-Content-SHA256 | header | string | yes | SHA-256: 64 lowercase hexadecimal digits |
Request body (application/octet-stream)
Responses: 204, 400, 401, 403, 404, 405, 409, 422, 503, 507
Example
curl -X PUT "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID/parts/$INDEX" \
-H "Authorization: Bearer $ARKVORY_TOKEN" \
-H "X-Content-SHA256: $X_CONTENT_SHA256" \
-H "Content-Type: application/octet-stream" \
--data-binary @fileComplete an upload in the background
POST /api/v1/repositories/{repository}/uploads/{id}/complete-async
Access: Repository permission: upload.complete; file keys: write · Retry: Re-read the job, then decide
Queues the completion of a pending upload for the worker service instead of doing it in the request, and returns the job at once with 202; follow it with getCompletionJob. Calling it again for the same upload returns the same job, and a job that failed for a transient reason is queued again. A queued job does not mean the artifact is published: only completed does. 409 upload_state if the upload is no longer pending; 507 queue_full when the caller has 100 open jobs or the server 10 000.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
Response 202
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
uploadId | string (uuid) | yes | — |
repository | string | yes | — |
owner | string | yes | — |
status | string | yes | one of queued, running, completed, failed |
generation | integer | yes | 0–2147483647 |
attempts | integer | yes | at least 0 |
credentialId | string (uuid) | no | Optional initiating managed key ID; never its secret. |
errorCode | string | yes | may be null |
Responses: 202, 400, 401, 403, 404, 405, 409, 422, 503, 507
Example
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID/complete-async" \
-H "Authorization: Bearer $ARKVORY_TOKEN"Get a completion job
GET HEAD /api/v1/jobs/{id}
Access: Repository permission: job.read; file keys: write · Retry: Safe to repeat (read)
Returns the state of a completion job queued with enqueueCompletion: queued, running, completed (the upload is published) or failed with an errorCode, plus the number of attempts. The worker tries up to five times with growing pauses; errors such as integrity_mismatch fail at once. Only the job's creator sees it; for anyone else it is a 404.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
id | path | string (uuid) | yes | — |
Response 200
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
uploadId | string (uuid) | yes | — |
repository | string | yes | — |
owner | string | yes | — |
status | string | yes | one of queued, running, completed, failed |
generation | integer | yes | 0–2147483647 |
attempts | integer | yes | at least 0 |
credentialId | string (uuid) | no | Optional initiating managed key ID; never its secret. |
errorCode | string | yes | may be null |
Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507
Example
curl -X GET "$ARKVORY_URL/api/v1/jobs/$ID" \
-H "Authorization: Bearer $ARKVORY_TOKEN"Create an upload session
POST /api/v1/repositories/{repository}/uploads
Access: Repository permission: upload.create; file keys: write · Retry: Safe to repeat with the same Idempotency-Key
Reserves an upload for one file described by name, size (a decimal string), sha256 and optional labels and metadata; returns 201 with the session (pending, valid for 7 days) and its Location. Idempotency-Key (1–128 letters, digits and _.:-) is required: the same key with the same description returns the same session, with a different description it is a 409 idempotency_mismatch. The size is reserved against the repository quota and the server's capacity at once (507). Then send the bytes whole with putUploadContent, or in parts with putUploadPart and finish with completeUpload.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
Idempotency-Key | header | string | yes | up to 128 characters |
Request body (application/json)
| Field | Type | Required | Rules |
|---|---|---|---|
name | string | yes | 1–240 characters |
size | string | yes | a whole number in decimal digits, sent as a string |
sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
labels | array of string | no | up to 32 items; each: up to 64 characters |
metadata | map of string | no | up to 32 entries |
Response 201
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
repository | string | yes | — |
status | string | yes | one of pending, available, cancelled |
createdAt | string (date-time) | yes | — |
expiresAt | string (date-time) | yes | — |
descriptor | object | yes | — |
descriptor.name | string | yes | 1–240 characters |
descriptor.size | string | yes | a whole number in decimal digits, sent as a string |
descriptor.sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
descriptor.labels | array of string | no | up to 32 items; each: up to 64 characters |
descriptor.metadata | map of string | no | up to 32 entries |
Responses: 201, 400, 401, 403, 404, 405, 409, 413, 415, 422, 503, 507
Example
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads" \
-H "Authorization: Bearer $ARKVORY_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"name":"<name>","size":"1024","sha256":"<sha256: SHA-256>"}'Get an upload
GET HEAD /api/v1/repositories/{repository}/uploads/{id}
Access: Repository permission: upload.read; file keys: write · Retry: Safe to repeat (read)
Returns the session with its status (pending, available once published, cancelled), its expiry and the declared descriptor. After a lost response to putUploadContent or completeUpload, read this first: available means the artifact is published under the same ID. Only the upload's creator sees it; for anyone else it is a 404.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
Response 200
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
repository | string | yes | — |
status | string | yes | one of pending, available, cancelled |
createdAt | string (date-time) | yes | — |
expiresAt | string (date-time) | yes | — |
descriptor | object | yes | — |
descriptor.name | string | yes | 1–240 characters |
descriptor.size | string | yes | a whole number in decimal digits, sent as a string |
descriptor.sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
descriptor.labels | array of string | no | up to 32 items; each: up to 64 characters |
descriptor.metadata | map of string | no | up to 32 entries |
Responses: 200, 400, 401, 403, 404, 409, 422, 503, 507
Example
curl -X GET "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID" \
-H "Authorization: Bearer $ARKVORY_TOKEN"Cancel an upload
DELETE /api/v1/repositories/{repository}/uploads/{id}
Access: Repository permission: upload.cancel; file keys: write · Retry: Re-read the upload, then decide
Cancels a pending upload and returns it with status cancelled; a published upload cannot be cancelled (409 upload_state). The received bytes are hidden at once but remain reserved against the quota until the repository's online cleanup (setCleanup, off by default) removes them after its grace period.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
Response 200
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
repository | string | yes | — |
status | string | yes | one of pending, available, cancelled |
createdAt | string (date-time) | yes | — |
expiresAt | string (date-time) | yes | — |
descriptor | object | yes | — |
descriptor.name | string | yes | 1–240 characters |
descriptor.size | string | yes | a whole number in decimal digits, sent as a string |
descriptor.sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
descriptor.labels | array of string | no | up to 32 items; each: up to 64 characters |
descriptor.metadata | map of string | no | up to 32 entries |
Responses: 200, 400, 401, 403, 404, 405, 409, 422, 503, 507
Example
curl -X DELETE "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID" \
-H "Authorization: Bearer $ARKVORY_TOKEN"Upload the whole file in one request
PUT /api/v1/repositories/{repository}/uploads/{id}/content
Access: Repository permission: upload.write, upload.complete; file keys: write · Retry: Re-read the upload, then decide
Streams the request body as the complete content of a pending upload, checks it against the declared size and SHA-256 (422 on mismatch) and publishes the artifact; the answer is the upload with status available. An interrupted request leaves nothing to resume: read the upload with getUpload, then send the file again from byte zero. Not for an upload that already has parts (409 upload_state); one request must also finish within the server's upload deadline (30 minutes by default), so send large files in parts.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
Request body (application/octet-stream)
Response 200
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
repository | string | yes | — |
status | string | yes | one of pending, available, cancelled |
createdAt | string (date-time) | yes | — |
expiresAt | string (date-time) | yes | — |
descriptor | object | yes | — |
descriptor.name | string | yes | 1–240 characters |
descriptor.size | string | yes | a whole number in decimal digits, sent as a string |
descriptor.sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
descriptor.labels | array of string | no | up to 32 items; each: up to 64 characters |
descriptor.metadata | map of string | no | up to 32 entries |
Responses: 200, 400, 401, 403, 404, 405, 409, 422, 503, 507
Example
curl -X PUT "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID/content" \
-H "Authorization: Bearer $ARKVORY_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @fileComplete an upload
POST /api/v1/repositories/{repository}/uploads/{id}/complete
Access: Repository permission: upload.complete; file keys: write · Retry: Re-read the upload, then decide
Assembles the stored parts in order, checks the whole file against the declared size and SHA-256 and publishes the artifact; returns the upload with status available. Calling it again for a published upload returns the same result, so it also recovers a completion whose answer was lost. A missing part is a 409 parts_incomplete, a content mismatch a 422; for very large files where the request might time out, use enqueueCompletion instead.
Parameters
| Name | In | Type | Required | Rules |
|---|---|---|---|---|
repository | path | string | yes | matches ^[a-z0-9][a-z0-9_-]{0,63}$ |
id | path | string (uuid) | yes | — |
Response 200
| Field | Type | Required | Rules |
|---|---|---|---|
id | string (uuid) | yes | — |
repository | string | yes | — |
status | string | yes | one of pending, available, cancelled |
createdAt | string (date-time) | yes | — |
expiresAt | string (date-time) | yes | — |
descriptor | object | yes | — |
descriptor.name | string | yes | 1–240 characters |
descriptor.size | string | yes | a whole number in decimal digits, sent as a string |
descriptor.sha256 | string | yes | SHA-256: 64 lowercase hexadecimal digits |
descriptor.labels | array of string | no | up to 32 items; each: up to 64 characters |
descriptor.metadata | map of string | no | up to 32 entries |
Responses: 200, 400, 401, 403, 404, 405, 409, 422, 503, 507
Example
curl -X POST "$ARKVORY_URL/api/v1/repositories/$REPOSITORY/uploads/$ID/complete" \
-H "Authorization: Bearer $ARKVORY_TOKEN"