Skip to main content

Artifacts

Library Artifacts are persistent deliverables produced by agents -- HTML reports, dashboards, plans, PDFs, documents. Metadata lives in the platform database; the body lives in S3 encrypted with SSE-KMS. The API hands out short-lived pre-signed URLs for direct downloads so the platform stays out of the data path.

All endpoints require authentication via X-API-Key header and the appropriate scope.


Artifact Object​

{
"_id": "art_abc123",
"title": "Q3 cost-explorer report",
"summary": "Highlights overspend in EU region",
"artifactType": "html_report",
"contentType": "text/html; charset=utf-8",
"contentSizeBytes": 28814,
"tags": ["finops", "q3"],
"linkedIds": [],
"category": null,
"currentVersion": 1,
"ownerId": "usr_mn0",
"ownerName": "Mona Nguyen",
"organizationId": "org_acme",
"sharedWith": [],
"isPublic": false,
"producerAgentId": "wf_iris",
"producerThreadId": "thr_pqr",
"producerSkillId": null,
"source": "agent:wf_iris",
"createdAt": "2026-05-17T10:00:00Z",
"updatedAt": "2026-05-17T10:00:00Z"
}

artifactType is one of: html_report, dashboard, pdf, document, plan, image. source is agent:<producerAgentId> when the artifact names the agent that produced it, otherwise agent:runtime.


GET /api/v1/library/artifacts​

List the artifacts you may see: your own, those shared with you, and those open to all users.

Scope: artifacts:read

Query Parameters

ParameterTypeRequiredDescription
artifactTypestringNoFilter by type
tagsstringNoComma-separated tags; an artifact must carry all of them
linkedIdsstringNoComma-separated ids; an artifact must be linked to all of them
producerAgentIdstringNoFilter to artifacts produced by a specific agent
producerSkillIdstringNoFilter to artifacts produced by a specific skill
qstringNoCase-insensitive match on title, summary or tags
limitintegerNoPage size (default 25, max 200)
cursorstringNometa.nextCursor of the previous page; omit for the first page

Response 200 OK -- paginated artifact list, most recently updated first:

{
"data": [ { "_id": "art_abc123", "title": "Q3 cost-explorer report", "...": "..." } ],
"meta": {
"total": 1,
"limit": 25,
"nextCursor": null,
"requestId": "req_abc123"
}
}

POST /api/v1/library/artifacts​

Create an artifact. The body is uploaded to S3 with SSE-KMS encryption; the row stores metadata + the canonical S3 key.

Scope: artifacts:write

Request Body

{
"title": "Q3 cost-explorer report",
"artifactType": "html_report",
"contentType": "text/html; charset=utf-8",
"encoding": "utf8",
"content": "<html>…</html>",
"summary": "Highlights overspend in EU region",
"tags": ["finops", "q3"],
"producerAgentId": "wf_iris",
"producerThreadId": "thr_pqr"
}

title, artifactType and content are required. content is read as base64 unless encoding is utf8.

Response 201 Created -- the new artifact's id:

{ "data": { "_id": "art_abc123" }, "meta": { "requestId": "req_abc123" } }

Saving again with the same title and the same content returns the existing artifact's id; the same title with different content adds a new version to that artifact and returns its id.


GET /api/v1/library/artifacts/:id​

Fetch a single artifact's metadata. Use GET /library/artifacts/:id/download-url for the body.

Scope: artifacts:read


PATCH /api/v1/library/artifacts/:id​

Update editable metadata: title, summary, tags. Content is immutable -- to replace it, create a new artifact.

Scope: artifacts:write

Request Body -- any subset:

{
"title": "Q3 cost-explorer report (final)",
"summary": "Updated summary",
"tags": ["finops", "q3", "approved"]
}

DELETE /api/v1/library/artifacts/:id​

Delete the artifact metadata and its S3 body. Idempotent.

Scope: artifacts:write

Response 204 No Content


GET /api/v1/library/artifacts/:id/download-url​

Return a short-lived pre-signed URL for direct S3 download. Default TTL is 5 minutes; cap is 15 minutes.

Scope: artifacts:read

Query Parameters

ParameterTypeRequiredDescription
ttlSecondsintegerNoTTL override (max 900).

Response 200 OK

{
"data": {
"url": "https://s3.…",
"expiresAt": "2026-05-17T10:05:00Z",
"ttlSeconds": 300,
"contentType": "text/html; charset=utf-8",
"sizeBytes": 28814
},
"meta": {
"requestId": "req_abc123"
}
}

POST /api/v1/library/artifacts/:id/refresh​

Re-read the S3 object's Content-Length and update contentSizeBytes on the row. Idempotent; useful after an out-of-band content replacement.

Scope: artifacts:write


Sharing​

Who can reach a artifact is the platform's one sharing shape: its owner, its members (role editor can use and change it, user can only use it) and its visibility (public: every user can find and use it; in a multi-tenant deployment, every user of its organization). Changing it stays with its owner and editors.

MethodPathDoesScope
GET/api/v1/library/artifacts/:id/permissionsOwner, members (userId, role) and visibilityartifacts:read
POST/api/v1/library/artifacts/:id/permissions/membersShare with a user: { "userId", "role": "editor" | "user" }artifacts:write
DELETE/api/v1/library/artifacts/:artifactId/permissions/members/:userIdStop sharing with a userartifacts:write
PATCH/api/v1/library/artifacts/:id/permissions{ "visibility": "public" | "private" }artifacts:write

Each, except a member's removal (204), answers the permissions as they are now:

{
"data": {
"resourceId": "<artifact id>",
"owner": "<user id>",
"members": [{ "userId": "<user id>", "role": "user" }],
"visibility": "private"
},
"meta": { "requestId": "req_abc123" }
}

GET /api/v1/library/artifacts/:id/versions​

An artifact's versions, newest first: each save under the same title adds one.

Scope: artifacts:read

ParameterTypeRequiredDescription
idstringYesArtifact id

Response 200 OK: every version, in one list.


POST /api/v1/library/artifacts/:artifactId/versions/:version/restore​

Restore an artifact to an earlier version: a new version equal to it is added.

Scope: artifacts:write

ParameterTypeRequiredDescription
artifactIdstringYesArtifact id
versionintegerYesThe version to restore

Response 200 OK: the artifact, at its new version.


Python SDK​

from strongly import Strongly

client = Strongly()
artifact = client.artifacts.create(
title="Q3 cost-explorer report",
artifact_type="html_report",
content_type="text/html; charset=utf-8",
content="<html>…</html>",
)
signed = client.artifacts.download_url(artifact.id, ttl_seconds=600)

Full client surface: list, create, retrieve, update, delete, download_url, refresh_size, share, unshare, toggle_public, toggle_org_share.

See also​