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,
      "url": "/artifacts/…",
      "public_url": null,
      "standalone_url": null,
      "created_at": "…",
      "updated_at": "…"
    }
  ],
  "count": 1
}

Each artifact includes three URL fields:

  • url - the signed-in editor link (always present).
  • public_url - the public share link, or null if the artifact is not shared (unlisted or public with a slug). Format: /share/a/<slug>.
  • standalone_url - for HTML artifacts only, the full-page view (e.g. /p/<slug>), or null otherwise.

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), workspace, unlisted, or public. Only unlisted and public mint 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"}'

POST /artifacts/:id/share — share an artifact (MCP tool)

Note: This is exposed only through the MCP server as the share_artifact tool, not as a REST endpoint. It publishes an artifact by link.

share_artifact (MCP tool)

Publish an artifact you own by link. Sets its visibility to "unlisted" (default, anyone with the link) or "public" (discoverable), creates its public slug if missing, and returns the shareable links.

Input:

  • artifact (string, required) - the artifact id or its exact title.
  • visibility (string, optional) - "unlisted" (default) or "public".

Returns:

  • url — the signed-in editor link.
  • public_url — the public share link, or null if not shared.
  • standalone_url — the full-page view for HTML artifacts, or null.
  • id — the artifact id.
  • visibility — the visibility setting.
  • public_slug — the generated slug.

Example via MCP (Claude):

Share my artifact "Dashboard" publicly.

This tells the assistant to use share_artifact with visibility: "public", which generates a public link if one doesn't exist.

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.

Visibility options and their effects:

  • private or workspace: only visible internally. No external link (public_url is null).
  • unlisted or public: generates a unique public_slug and mints shareable links.
    • All artifacts get public_url — the shareable public link at /share/a/<public_slug>.
    • HTML artifacts only also get standalone_url — a full-screen, chrome-free page at /p/<public_slug>. Use this for dashboards, diagrams, or landing pages you want to host at the app's own URL.

Important: Public share routes resolve by public_slug, not by artifact id. This prevents accidental exposure — an agent building a link from the artifact id will get a 404, forcing it to use the ready-made public_url field instead. Always use public_url when sharing; never construct share links from the id.

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