Skip to main content
API reference sections

HTTP API reference

Artifacts

Artifact families and immutable versions, their provenance and content, and run authorities.

19 operations. The contract has no example values, so example bodies are generated from each schema: every field is shown with a placeholder of its type.

The artifact families of a workspace

GET/v1/artifacts/families

The families the caller may read, oldest first; retired ones only with include_retired=true.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_list_families

Parameters

NameInTypeDescription
workspacerequiredquerystring (uuid)
include_retiredqueryboolean

Default false

Responses

StatusDescriptionBody
200See above.ListFamiliesResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "families": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "workspace": "00000000-0000-4000-8000-000000000000",
      "title": "string",
      "created_by_run": "00000000-0000-4000-8000-000000000000",
      "created_at_ms": 0,
      "retired_at_ms": 0
    }
  ]
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/families?workspace=$WORKSPACE" \
  -H "Authorization: Bearer $KORU_TOKEN"

Create an artifact family

POST/v1/artifacts/families

The family. The caller mints the id; a second creation under the same id is refused with artifact_family_exists rather than made twice.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_create_family

Request body (required)

application/json CreateFamilyRequest

FieldTypeDescription
family_idrequiredArtifactFamilyId
workspacerequiredWorkspaceId
titlerequiredArtifactTitle

The title a result is named by on a device that cannot open its bytes (D27). A title is content: it is redacted like the objective.

created_by_runRunId or null
Example request body
{
  "family_id": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "created_by_run": "00000000-0000-4000-8000-000000000000"
}

Responses

StatusDescriptionBody
200See above.ArtifactFamily
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "id": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "created_by_run": "00000000-0000-4000-8000-000000000000",
  "created_at_ms": 0,
  "retired_at_ms": 0
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/families" \
  -H "Authorization: Bearer $KORU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "family_id": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "created_by_run": "00000000-0000-4000-8000-000000000000"
}'

A family with its versions

GET/v1/artifacts/families/{family}

The family and every version under it, by ordinal.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_family

Parameters

NameInTypeDescription
familyrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.FamilyResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "family": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workspace": "00000000-0000-4000-8000-000000000000",
    "title": "string",
    "created_by_run": "00000000-0000-4000-8000-000000000000",
    "created_at_ms": 0,
    "retired_at_ms": 0
  },
  "versions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "family": "00000000-0000-4000-8000-000000000000",
      "ordinal": 0,
      "blob": "string",
      "size_bytes": 0,
      "mime": "string",
      "filename": "string",
      "produced_by": {
        "run": "00000000-0000-4000-8000-000000000000",
        "generation": 0
      },
      "registration_id": "00000000-0000-4000-8000-000000000000",
      "derived_from": "00000000-0000-4000-8000-000000000000",
      "created_at_ms": 0
    }
  ]
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/families/$FAMILY" \
  -H "Authorization: Bearer $KORU_TOKEN"

Retire a family

POST/v1/artifacts/families/{family}/retire

The family with retired_at_ms set. Its versions stay readable; it accepts no new version. Retiring twice keeps the first mark.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_retire_family

Parameters

NameInTypeDescription
familyrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.ArtifactFamily
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "id": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "title": "string",
  "created_by_run": "00000000-0000-4000-8000-000000000000",
  "created_at_ms": 0,
  "retired_at_ms": 0
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/families/$FAMILY/retire" \
  -H "Authorization: Bearer $KORU_TOKEN"

Register an immutable version of a family

POST/v1/artifacts/families/{family}/versions

The version, and whether an earlier call with the same registration_id had already made it. Metadata only: the blob must already be in the family's workspace (PUT /v1/workspaces/{id}/blobs), or the answer is blob_not_found. The size recorded is the Store's.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_register_version

Parameters

NameInTypeDescription
familyrequiredpathstring (uuid)

Request body (required)

application/json RegisterVersionRequest

FieldTypeDescription
registration_idrequiredRegistrationId
blobrequiredBlobHash

<algorithm>:<digest> - b3:<64 hex>.

The algorithm is in the value because a hash that does not say what it is cannot be migrated: adopting a second one has to be additive, or every document already written is orphaned.

mimerequiredMediaType

A type/subtype media type, ASCII and lowercased, as the blob store records it. Not content: it prints in full.

filenameFilename or null
produced_byProducedBy or null
derived_fromArtifactVersionId or null
Example request body
{
  "registration_id": "00000000-0000-4000-8000-000000000000",
  "blob": "string",
  "mime": "string",
  "filename": "string",
  "produced_by": {
    "run": "00000000-0000-4000-8000-000000000000",
    "generation": 0
  },
  "derived_from": "00000000-0000-4000-8000-000000000000"
}

Responses

StatusDescriptionBody
200See above.RegisterVersionResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "version": {
    "id": "00000000-0000-4000-8000-000000000000",
    "family": "00000000-0000-4000-8000-000000000000",
    "ordinal": 0,
    "blob": "string",
    "size_bytes": 0,
    "mime": "string",
    "filename": "string",
    "produced_by": {
      "run": "00000000-0000-4000-8000-000000000000",
      "generation": 0
    },
    "registration_id": "00000000-0000-4000-8000-000000000000",
    "derived_from": "00000000-0000-4000-8000-000000000000",
    "created_at_ms": 0
  },
  "retried": false
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/families/$FAMILY/versions" \
  -H "Authorization: Bearer $KORU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "registration_id": "00000000-0000-4000-8000-000000000000",
  "blob": "string",
  "mime": "string",
  "filename": "string",
  "produced_by": {
    "run": "00000000-0000-4000-8000-000000000000",
    "generation": 0
  },
  "derived_from": "00000000-0000-4000-8000-000000000000"
}'

One artifact version

GET/v1/artifacts/versions/{version}

The version: identity, family, ordinal, blob address, size, media type, filename, producer, registration id and derived_from.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_version

Parameters

NameInTypeDescription
versionrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.ArtifactVersion
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "id": "00000000-0000-4000-8000-000000000000",
  "family": "00000000-0000-4000-8000-000000000000",
  "ordinal": 0,
  "blob": "string",
  "size_bytes": 0,
  "mime": "string",
  "filename": "string",
  "produced_by": {
    "run": "00000000-0000-4000-8000-000000000000",
    "generation": 0
  },
  "registration_id": "00000000-0000-4000-8000-000000000000",
  "derived_from": "00000000-0000-4000-8000-000000000000",
  "created_at_ms": 0
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/versions/$VERSION" \
  -H "Authorization: Bearer $KORU_TOKEN"

Refused: a version cannot be changed (also PUT and DELETE)

PATCH/v1/artifacts/versions/{version}

409 artifact_version_immutable, always - the same code the database raises. Register a new version, or retire the family.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_version_immutable

Parameters

NameInTypeDescription
versionrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example request
curl -X PATCH "http://127.0.0.1:$PORT/v1/artifacts/versions/$VERSION" \
  -H "Authorization: Bearer $KORU_TOKEN"

A version's provenance

GET/v1/artifacts/versions/{version}/provenance

The version, every ancestor reached through derived_from (nearest first), and every run that consumed or produced any of them.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_provenance

Parameters

NameInTypeDescription
versionrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.Provenance
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "subject": {
    "id": "00000000-0000-4000-8000-000000000000",
    "family": "00000000-0000-4000-8000-000000000000",
    "ordinal": 0,
    "blob": "string",
    "size_bytes": 0,
    "mime": "string",
    "filename": "string",
    "produced_by": {
      "run": "00000000-0000-4000-8000-000000000000",
      "generation": 0
    },
    "registration_id": "00000000-0000-4000-8000-000000000000",
    "derived_from": "00000000-0000-4000-8000-000000000000",
    "created_at_ms": 0
  },
  "ancestors": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "family": "00000000-0000-4000-8000-000000000000",
      "ordinal": 0,
      "blob": "string",
      "size_bytes": 0,
      "mime": "string",
      "filename": "string",
      "produced_by": {
        "run": "00000000-0000-4000-8000-000000000000",
        "generation": 0
      },
      "registration_id": "00000000-0000-4000-8000-000000000000",
      "derived_from": "00000000-0000-4000-8000-000000000000",
      "created_at_ms": 0
    }
  ],
  "runs": [
    {
      "run": "00000000-0000-4000-8000-000000000000",
      "version": "00000000-0000-4000-8000-000000000000",
      "role": "input",
      "linked_at_ms": 0
    }
  ],
  "deleted_runs": [
    "00000000-0000-4000-8000-000000000000"
  ]
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/versions/$VERSION/provenance" \
  -H "Authorization: Bearer $KORU_TOKEN"

A version's bytes

GET/v1/artifacts/versions/{version}/content

The Store's answer for the version's blob, forwarded as it is: application/octet-stream with the blob's media type and filename headers, or the Store's own failure. Requires store.read_documents as well.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_content

Parameters

NameInTypeDescription
versionrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.string (binary)application/octet-stream
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/versions/$VERSION/content" \
  -H "Authorization: Bearer $KORU_TOKEN"

POST/v1/artifacts/versions/{version}/runs

The link. Idempotent on (run, version, role).

Authorization
Bearer token with artifacts.write
Operation id
artifacts_link_run

Parameters

NameInTypeDescription
versionrequiredpathstring (uuid)

Request body (required)

application/json LinkRunRequest

FieldTypeDescription
runrequiredRunId
rolerequiredLinkRole

How a run touched a version: read it as an input, or produced it as an output. A closed domain, CHECKed by the database as well.

Example request body
{
  "run": "00000000-0000-4000-8000-000000000000",
  "role": "input"
}

Responses

StatusDescriptionBody
200See above.RunLink
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "version": "00000000-0000-4000-8000-000000000000",
  "role": "input",
  "linked_at_ms": 0
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/versions/$VERSION/runs" \
  -H "Authorization: Bearer $KORU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "run": "00000000-0000-4000-8000-000000000000",
  "role": "input"
}'

Issue a run's authority and its first endpoint token

POST/v1/artifacts/authorities

The run's endpoint URL (<gateway>/v1/runs/{run}/mcp, stable across attempts) and the bearer for this attempt - shown once; a later read never returns it. The grant set is the request's, frozen for the attempt (D28). A run that already has an authority is refused with authority_exists: advance its generation instead.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_issue_authority

Request body (required)

application/json IssueAuthorityRequest

FieldTypeDescription
runrequiredRunId
workspacerequiredWorkspaceId
generationrequiredAttemptGeneration

Which attempt of a run is current - the fence §7.5 and §7.6 rely on.

A monotonic counter per run, starting at [AttemptGeneration::FIRST]. An event, an MCP call or a session lookup carrying an older generation may not touch status, control or authority; see [crate::AttemptGeneration::admits]. It is a counter rather than an id so "older" is a comparison, not a lookup.

grantsarray of WorkspaceId

Default []

run_workspacerequiredRunWorkspace

The run's working scope on this device. A path is content (standing requirement 7): it is stored so the gateway can resolve Register paths against it, and it is redacted from every Debug rendering.

Example request body
{
  "run": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "generation": 0,
  "grants": [],
  "run_workspace": "string"
}

Responses

StatusDescriptionBody
200See above.IssuedAuthority
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "generation": 0,
  "url": "string",
  "token": "string"
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/authorities" \
  -H "Authorization: Bearer $KORU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "run": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "generation": 0,
  "grants": [],
  "run_workspace": "string"
}'

A run's authority record

GET/v1/artifacts/authorities/{run}

The record without its token and without its working-scope path: workspace, current generation, grants, state.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_authority

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.AuthorityView
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "generation": 0,
  "grants": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "state": "active",
  "created_at_ms": 0,
  "revoked_at_ms": 0
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/authorities/$RUN" \
  -H "Authorization: Bearer $KORU_TOKEN"

A fresh attempt: advance the run's generation under a fresh token

POST/v1/artifacts/authorities/{run}/generation

The same endpoint URL and a new bearer. The previous bearer is retired and answers stale_generation from then on; the grants are re-read from the record and never widened. A generation that is not strictly newer is refused with stale_generation; a revoked run with authority_revoked.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_advance_generation

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Request body (required)

application/json AdvanceGenerationRequest

FieldTypeDescription
generationrequiredAttemptGeneration

Which attempt of a run is current - the fence §7.5 and §7.6 rely on.

A monotonic counter per run, starting at [AttemptGeneration::FIRST]. An event, an MCP call or a session lookup carrying an older generation may not touch status, control or authority; see [crate::AttemptGeneration::admits]. It is a counter rather than an id so "older" is a comparison, not a lookup.

Example request body
{
  "generation": 0
}

Responses

StatusDescriptionBody
200See above.IssuedAuthority
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "generation": 0,
  "url": "string",
  "token": "string"
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/authorities/$RUN/generation" \
  -H "Authorization: Bearer $KORU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "generation": 0
}'

Revoke a run's authority

POST/v1/artifacts/authorities/{run}/revoke

The record marked revoked. A state change every later call at the run's endpoint reads (authority_revoked) - no callback, nothing to refresh. Idempotent.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_revoke_authority

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.AuthorityView
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "workspace": "00000000-0000-4000-8000-000000000000",
  "generation": 0,
  "grants": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "state": "active",
  "created_at_ms": 0,
  "revoked_at_ms": 0
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/authorities/$RUN/revoke" \
  -H "Authorization: Bearer $KORU_TOKEN"

Where the run worked, as this device resolved it

GET/v1/artifacts/authorities/{run}/workspace

The absolute working folder the run's authority record holds -- the one read that carries a path back out of this store, for the one caller entitled to it: emptying the trash, which has to remove that folder when Koru made it. Behind the write scope rather than the read one, because reading it is not what it is for. Refused with authority_not_found for a run this device never started.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_authority_workspace

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.RunWorkspaceResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "run_workspace": "string"
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/authorities/$RUN/workspace" \
  -H "Authorization: Bearer $KORU_TOKEN"

The run was deleted: forget its authority

POST/v1/artifacts/authorities/{run}/forget

The record, its grants and its tokens are removed -- there is nothing left for them to authorize -- and one row saying the run was deleted takes their place, so a result the person chose to keep says 'a run that was deleted' rather than printing an id that resolves to nothing. Idempotent; held_authority is false, not an error, for a run that never had one.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_forget_authority

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.ForgetAuthorityResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "run": "00000000-0000-4000-8000-000000000000",
  "held_authority": false
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/authorities/$RUN/forget" \
  -H "Authorization: Bearer $KORU_TOKEN"

The versions a run has registered

GET/v1/artifacts/runs/{run}/versions

Every version whose producer is the run, oldest first - what the orchestrator reads at a turn boundary to decide whether the run delivered anything (D29) and to publish delegate.artifact.registered.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_run_versions

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Responses

StatusDescriptionBody
200See above.RunVersionsResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "versions": [
    {
      "id": "00000000-0000-4000-8000-000000000000",
      "family": "00000000-0000-4000-8000-000000000000",
      "ordinal": 0,
      "blob": "string",
      "size_bytes": 0,
      "mime": "string",
      "filename": "string",
      "produced_by": {
        "run": "00000000-0000-4000-8000-000000000000",
        "generation": 0
      },
      "registration_id": "00000000-0000-4000-8000-000000000000",
      "derived_from": "00000000-0000-4000-8000-000000000000",
      "created_at_ms": 0
    }
  ]
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/runs/$RUN/versions" \
  -H "Authorization: Bearer $KORU_TOKEN"

What a workspace's runs wrote and never registered

GET/v1/artifacts/unregistered

Every run of the workspace with an authority on this device, newest first: how many versions it has registered (zero is D29's finished-having-registered-nothing), whether its .artifacts/<RunId>/ folder is still there, and the files inside it that are not results yet. A link is never followed and never listed; the scan stops at 8 levels and 500 files, and says so with truncated.

Authorization
Bearer token with artifacts.read
Operation id
artifacts_unregistered

Parameters

NameInTypeDescription
workspacerequiredquerystring (uuid)
include_retiredqueryboolean

Default false

Responses

StatusDescriptionBody
200See above.UnregisteredResponse
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "runs": [
    {
      "run": "00000000-0000-4000-8000-000000000000",
      "workspace": "00000000-0000-4000-8000-000000000000",
      "folder_present": false,
      "registered": 0,
      "unregistered": [
        {
          "path": "string",
          "size_bytes": 0,
          "modified_at_ms": 0
        }
      ],
      "truncated": false
    }
  ]
}
Example request
curl "http://127.0.0.1:$PORT/v1/artifacts/unregistered?workspace=$WORKSPACE" \
  -H "Authorization: Bearer $KORU_TOKEN"

Register a file the run left in its results folder (D19)

POST/v1/artifacts/runs/{run}/register

The version and its family. The path is resolved under the same register path rule the run's own tools obey - canonical, inside <run-workspace>/.artifacts/<RunId>/, no traversal, no symlink or junction, unchanged between listing and read - and refused with the same stable codes. The workspace, the family's identity and the provenance all come from the run's durable authority record, never from the request; a revoked run still answers, because revocation withdraws the agent's reach and not the person's. Absent a title, the file's last path segment names the result. Registering the same bytes twice is the same version; the same path with new bytes is the next one.

Authorization
Bearer token with artifacts.write
Operation id
artifacts_register_file

Parameters

NameInTypeDescription
runrequiredpathstring (uuid)

Request body (required)

application/json RegisterFileRequest

FieldTypeDescription
pathrequiredRelativePath

A file's place inside a run's .artifacts/<RunId>/ folder: /-separated, never absolute, never carrying a parent-directory step.

Content, like a filename, so its Debug redacts. It is a statement of where to look, never an authority to look there: the register path rule (staging::stage) still resolves it, walks it for links and proves containment. Refusing the obvious faults here as well means a listing this type could not have produced can never be echoed back as a registration.

titleArtifactTitle or null
mimeMediaType or null
Example request body
{
  "path": "string",
  "title": "string",
  "mime": "string"
}

Responses

StatusDescriptionBody
200See above.RegisteredFile
400

The request body, query or path identity is invalid

ArtifactFailure
401

The gateway bearer is absent or invalid

ArtifactFailure
403

The bearer lacks the operation's artifact scope, or the principal holds no access on the family

ArtifactFailure
404

No family, version or blob has that id

ArtifactFailure
409

The operation conflicts with an immutable version, a retired family, an existing family id or an earlier registration

ArtifactFailure
413

The metadata body exceeds the artifact route limit; bytes go through the Store's blob route

ArtifactFailure
503

artifacts.db did not open; the artifacts capability is absent

ArtifactFailure
Example 200 response
{
  "version": {
    "id": "00000000-0000-4000-8000-000000000000",
    "family": "00000000-0000-4000-8000-000000000000",
    "ordinal": 0,
    "blob": "string",
    "size_bytes": 0,
    "mime": "string",
    "filename": "string",
    "produced_by": {
      "run": "00000000-0000-4000-8000-000000000000",
      "generation": 0
    },
    "registration_id": "00000000-0000-4000-8000-000000000000",
    "derived_from": "00000000-0000-4000-8000-000000000000",
    "created_at_ms": 0
  },
  "family": {
    "id": "00000000-0000-4000-8000-000000000000",
    "workspace": "00000000-0000-4000-8000-000000000000",
    "title": "string",
    "created_by_run": "00000000-0000-4000-8000-000000000000",
    "created_at_ms": 0,
    "retired_at_ms": 0
  },
  "retried": false
}
Example request
curl -X POST "http://127.0.0.1:$PORT/v1/artifacts/runs/$RUN/register" \
  -H "Authorization: Bearer $KORU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "path": "string",
  "title": "string",
  "mime": "string"
}'

Generated from contract version 1. Last updated .

Privacy choices

Choose which optional tools Koru may use on this site. Your choice is saved in a cookie in this browser for 12 months. Privacy policy

Privacy choices

Keep you signed in, protect forms and remember your language and this choice.

Always on

PostHog and Google Analytics 4 measure page views and actions such as downloads, using cookies or local storage.

PostHog records how pages are used, with form inputs masked and private pages excluded. Needs Analytics.

Ahrefs Web Analytics measures visits and where they come from, and Google Ads measures whether our ads led to a visit or download.