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"],
"ownerId": "usr_mn0",
"organizationId": "org_acme",
"sharedWith": [],
"isPublic": false,
"permissions": { "sharedToOrg": false },
"producerAgentId": "wf_iris",
"producerThreadId": "thr_pqr",
"producerSkillId": null,
"agentId": null,
"appId": null,
"workflowId": "wf_iris",
"source": "agent:runtime",
"createdAt": "2026-05-17T10:00:00Z",
"updatedAt": "2026-05-17T10:00:00Z"
}

artifactType is one of: html_report, dashboard, pdf, document, plan.


GET /api/v1/artifacts

List artifacts visible to the caller (owner + sharedWith + isPublic + sharedToOrg per scope).

Scope: artifacts:read

Query Parameters

ParameterTypeRequiredDescription
artifactTypestringNoFilter by type
tagstringNoSingle-tag filter
producerAgentIdstringNoFilter to artifacts produced by a specific agent
producerThreadIdstringNoFilter to artifacts from a specific thread
searchstringNoFull-text search on title + summary
limitintegerNoPage size (default 50)
offsetintegerNoSkip count

Response 200 OK — paginated artifact list.


POST /api/v1/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",
"content": "<html>…</html>",
"summary": "Highlights overspend in EU region",
"tags": ["finops", "q3"],
"producerAgentId": "wf_iris",
"producerThreadId": "thr_pqr"
}

For binary types (pdf), content should be base64-encoded.

Response 201 Created — full artifact object.


GET /api/v1/artifacts/:id

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

Scope: artifacts:read


PATCH /api/v1/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/artifacts/:id

Delete the artifact metadata and its S3 body. Idempotent.

Scope: artifacts:write

Response 204 No Content


GET /api/v1/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
}
}

POST /api/v1/artifacts/:id/refresh-size

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


POST /api/v1/artifacts/:id/share

Share an artifact with one user. Owner / admin only. Cross-org targets are rejected in multi-tenant deployments.

Scope: artifacts:write

Request Body

{ "userId": "usr_target" }

POST /api/v1/artifacts/:id/unshare

Unshare from one user. Owner / admin only.

Scope: artifacts:write

Request Body

{ "userId": "usr_target" }

POST /api/v1/artifacts/:id/toggle-public

Flip isPublic. Owner / admin only.

Scope: artifacts:write

Response 200 OK

{ "data": { "isPublic": true } }

POST /api/v1/artifacts/:id/toggle-org-share

Flip permissions.sharedToOrg, distinct from isPublic. Lets you share with your org without going fully public. Owner / admin only.

Scope: artifacts:write


PATCH /api/v1/artifacts/:id/scope

Replace the scope tuple (agentId, appId, workflowId). Owner-only. Empty scope = user-global.

Scope: artifacts:write

Request Body

{ "scope": { "agentId": null, "appId": null, "workflowId": "wf_iris" } }

Python SDK

from strongly import Strongly

client = Strongly()
artifact = client.artifacts.create({
"title": "Q3 cost-explorer report",
"artifactType": "html_report",
"contentType": "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, update_scope.

See also