# Artifacts (/docs/concepts/artifacts)



An artifact is a durable, indexed output copied from a sandbox workspace to
object storage. Artifacts outlive the sandbox: once exported, you can list
and download them after the sandbox is destroyed. Export is always
explicit — CrowNest never copies files out of a sandbox automatically.

## Explicit export only [#explicit-export-only]

Nothing leaves the workspace unless you ask. When a sandbox expires or is
killed, its filesystem is gone; only files you exported as artifacts
survive.

There are two ways to create an artifact.

### Create via the API [#create-via-the-api]

`POST /v1/sandboxes/{id}/artifacts` with body `path` (a file inside
`/workspace`) and optional `name` copies the file to object storage and
returns the artifact. The request requires both the `artifact:create` and
`file:read` scopes and supports an `Idempotency-Key` header.

### Collect on command completion [#collect-on-command-completion]

The synchronous `run` endpoint accepts a `collect` array of
`{ path, name? }` entries and a `collectOn` setting:

* `collectOn: "success"` (default) — collect only when the command exits
  successfully.
* `collectOn: "always"` — collect regardless of how the command ends.

Using `collect` requires the `artifact:create` scope in addition to
`command:run`. The asynchronous `start` endpoint doesn't accept `collect`
or `collectOn`.

## Collection status [#collection-status]

Collection is tracked separately from the command result. The command
object carries a `collectStatus` independent of its own `status` and
`exitCode`:

| `collectStatus` | Meaning                                                                                      |
| --------------- | -------------------------------------------------------------------------------------------- |
| `not_requested` | The command had no `collect` entries.                                                        |
| `pending`       | Collection is still in progress.                                                             |
| `succeeded`     | Every requested file was exported.                                                           |
| `partial`       | Some files were exported, some failed.                                                       |
| `failed`        | No requested file could be exported.                                                         |
| `skipped`       | Collection didn't run, for example because `collectOn` was `success` and the command failed. |

A command can exit successfully while collection fails (for example, a
listed file was never created), and details land in `collectErrors`. Check
`collectStatus` rather than assuming a successful command means successful
collection.

## Retention [#retention]

Artifacts are retained for a configurable window, then cleaned up. See
[Usage and billing](/docs/concepts/usage-and-billing) for the current
retention period. You can delete an artifact early with
`DELETE /v1/artifacts/{artifactId}`.

## Downloads [#downloads]

Downloads use short-lived signed URLs rather than permanent links. Request
one with `POST /v1/artifacts/{artifactId}/download-url`, which returns
`{ url, method: "GET", headers, authMode: "api_key" }`. Fetch the URL
promptly; request a fresh one when it expires.

To browse what exists, `GET /v1/sandboxes/{id}/artifacts` lists a sandbox's
artifacts and `GET /v1/artifacts/{artifactId}` returns one. Each artifact
records its `name`, `sourcePath`, `sizeBytes`, `contentType`, and
`createdAt`.

## Next steps [#next-steps]

* [Commands](/docs/concepts/commands) — collect outputs as part of a
  command run.
* [Files and the workspace](/docs/concepts/files) — the source filesystem
  artifacts are exported from.
* [Usage and billing](/docs/concepts/usage-and-billing) — retention and
  storage quotas by plan.
* [Artifacts API reference](/docs/api/artifacts)
