SupaNet
Building on SupaNet

Artifact API reference

Complete reference for the REST CRUD API around artifacts.

The Artifacts CRUD API (supabase/functions/artifacts, deployed public) is a plain-REST interface for pushing artifacts in and out of SupaNet without MCP or holding a Supabase session. Every call is authenticated by a bearer token (either a personal mcp_tokens token or a Supabase session JWT), and the function runs as the token's owner with re-enforced ownership in code (using the service role + code checks, not RLS).

Base URL

https://<your-project>.supabase.co/functions/v1/artifacts

A bare GET with no Authorization header, or GET /artifacts/docs, returns plain-text documentation.

Endpoints

MethodPathPurpose
GET/artifactsList your artifacts (metadata by default).
POST/artifactsCreate an artifact.
GET/artifacts/:idRead one (includes content and collections).
PATCH | PUT/artifacts/:idUpdate fields; add collection tags.
DELETE/artifacts/:idDelete one.

GET /artifacts — list

Query parameters (all optional):

ParamMeaning
collectionOnly artifacts in this collection (name or id).
typeFilter by type: markdown, code, html, or text.
qTitle contains (case-insensitive).
include=contentInclude the full content in each row (omitted by default).
limit1–200, default 50.
offsetPaging offset, default 0.

Response:

{
  "artifacts": [
    {
      "id": "…",
      "title": "Hello",
      "type": "markdown",
      "language": null,
      "visibility": "private",
      "public_slug": null,
      "share_url": null,
      "created_at": "…",
      "updated_at": "…"
    }
  ],
  "count": 1
}

POST /artifacts — create

JSON body:

FieldRequiredTypeNotes
titleyesstring
contentyesstringThe artifact body.
typenostringmarkdown (default), code, html, or text.
languagenostringHint for code artifacts (e.g., ts, py).
visibilitynostringprivate (default), unlisted, or public. Non-private mints a public_slug.
collectionnostringCollection name or id (created if missing).
collectionsnoarrayArray of collection names/ids (created if missing).

Returns 201 with the created artifact (including content and its collections).

Example:

curl -X POST "https://<project>.supabase.co/functions/v1/artifacts" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My Blog Post",
    "content": "# Hello\n\nThis is a post.",
    "type": "markdown",
    "collection": "Blog"
  }'

GET /artifacts/:id — read

Returns the full artifact including content and the list of collections it belongs to.

Example:

curl "https://<project>.supabase.co/functions/v1/artifacts/<id>" \
  -H "Authorization: Bearer $TOKEN"

Returns 404 if not found or not owned by the token's user.

PATCH /artifacts/:id (or PUT) — update

Send only the fields you want to change:

FieldType
titlestring
contentstring
typestring
languagestring
visibilitystring

Passing collection or collections adds the artifact to those collections. Existing tags are kept; this API cannot remove tags (use the app UI for that). Flipping visibility to non-private mints a share link if one did not exist.

Returns the updated artifact.

Example:

curl -X PATCH "https://<project>.supabase.co/functions/v1/artifacts/<id>" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content": "# Updated", "visibility": "public"}'

DELETE /artifacts/:id

Deletes the artifact. Returns { "deleted": true, "id": "…" }.

Example:

curl -X DELETE "https://<project>.supabase.co/functions/v1/artifacts/<id>" \
  -H "Authorization: Bearer $TOKEN"

Returns 404 if not found or not owned by the token's user.

Errors

All errors are JSON: { "error": "message" } with an appropriate HTTP status:

StatusMeaning
400Bad input (missing required field, invalid type, etc.).
401Missing or invalid bearer token.
404Artifact not found or not owned by the token's user.
405Wrong HTTP method or path (e.g., POST to /artifacts/:id).
500Server error.

Collections

A collection is a named group of artifacts you can chat with in SupaNet. When pushing artifacts via this API:

  • Reference by name (any string; created automatically if it does not exist) or by id (UUID).
  • Collection tagging is additive: update operations add to existing tags, they do not replace them.
  • To remove a tag, use the app UI.

Collections respect workspace membership: a collection you create is private by default, but it can be shared with the workspace if you mark it shared in the UI.

Setting visibility to unlisted or public mints a public_slug:

  • For HTML artifacts: you also get a share_url — a full-screen, sandboxed page served by the app at /p/<public_slug>. The HTML runs in a secure iframe so user code never executes on the app origin. Link it directly.
  • For other types: build the in-app link yourself: https://<app-origin>/share/a/<public_slug>.

Private artifacts are never exposed this way.

Authentication note

The bearer token can be a personal connection token (mcp_tokens) or a Supabase session JWT (verified server-side via auth.getUser). Connection tokens should be treated like a password:

  • Rotate it if leaked.
  • Revoke it anytime from Settings → Connect Claude.
  • Requests are authenticated at the token → owner level; the function runs with the service role and re-enforces ownership in code.

CORS

The API ships with permissive CORS headers. You can call it from a browser.

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS

Examples

See Artifact API for use-case examples and typical workflows.

On this page