Document API ReferenceVersion v1Auth Bearer · API key

API
reference.

Everything you need to upload images, publish HTML artifacts, host raw CSV files, store reusable datasets, and create routed multi-page apps via the my-site.io REST API.

§ 01

Authentication.

All API requests require a Bearer token in the Authorization header. Bootstrap a sandbox workspace programmatically, or sign in and manage a claimed workspace from the dashboard.

  1. 01Agent-first path: call POST /v1/workspaces to get an unclaimed workspace key and claim URL instantly.
  2. 02Human-claim path: visit the claim URL and sign in with GitHub to unlock claimed-workspace capabilities such as apps.
  3. 03Sign in with GitHub to create or access your dashboard account directly.
  4. 04Open the dashboard after sign-in.
  5. 05Generate your API key from the dashboard. It is displayed once — copy it and store it securely.
  6. 06If you lose your key, regenerate it from the dashboard. Regenerating invalidates the old key.
Header format
authorization header
Authorization: Bearer your_artifact_api_key

API keys are prefixed with artifact_ and should be kept secret. Use GET /v1/whoami and GET /v1/usage to inspect the workspace tied to the current key.

§ 02

Skill reference (for agents).

Fetch the complete API reference as plain text — designed to be included in an AI agent's system prompt or tool context. No authentication required.

GET /skill.md
curl https://www.my-site.io/skill.md

Returns text/plain covering workspace bootstrap, all endpoints, catalog integration, limits, and a typical agent workflow. Give this to your agent so it knows everything it can do.

§ 03

Optional client headers.

Agent and SDK callers can send lightweight client metadata for better analytics and debugging. These headers are optional and do not affect authentication or response shape.

client headers
X-Artifact-Title: My Dashboard
X-Client-Name: codex-cli
X-Client-Version: 1.2.3
X-Run-Id: run_abc123

X-Artifact-Title sets a display name for the artifact shown in your dashboard. Supported on POST and PUT. X-CSV-Title does the same for hosted CSV files.

§ 04

Artifacts.

POST/v1/artifacts

Create artifact

Upload raw HTML and receive a live public URL. The HTML is stored and immediately accessible.

Example request
POST /v1/artifacts
curl -X POST https://adjoining-bison-868.convex.site
/v1/artifacts \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: text/html" \
  -H "X-Artifact-Title: My Page" \
  -d '<html><body><h1>Hello World</h1></body></html>'
Example response
json response
{
  "id": "abc123",
  "url": "https://adjoining-bison-868.convex.site
/a/abc123"
}

Free tier: max 3 active artifacts with 24-hour expiry. Pro tier: higher limits, no expiry. The X-Artifact-Title header is optional and sets a display name visible in the dashboard.

PUT/v1/artifacts/:id

Update artifact

Replace the HTML content of an existing artifact you own. The public URL stays the same.

Example request
PUT /v1/artifacts/:id
curl -X PUT https://adjoining-bison-868.convex.site
/v1/artifacts/abc123 \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: text/html" \
  -H "X-Artifact-Title: Updated Title" \
  -d '<html><body><h1>Updated content</h1></body></html>'
Example response
json response
{
  "id": "abc123",
  "url": "https://adjoining-bison-868.convex.site
/a/abc123",
  "updated": true
}
GET/v1/artifacts

List artifacts

Retrieve a list of all your active artifacts with their metadata.

Example request
GET /v1/artifacts
curl https://adjoining-bison-868.convex.site
/v1/artifacts \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
[
  {
    "id": "abc123",
    "title": "My Page",
    "url": "https://adjoining-bison-868.convex.site
/a/abc123",
    "createdAt": 1710900000000,
    "updatedAt": 1710900000000
  }
]

Only returns your own artifacts. Soft-deleted artifacts are excluded.

DELETE/v1/artifacts/:id

Delete artifact

Soft-delete an artifact you own. The public URL will return 404 after deletion.

Example request
DELETE /v1/artifacts/:id
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/artifacts/abc123 \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "id": "abc123",
  "deleted": true
}

Deleting an artifact frees up your quota slot on the free tier.

§ 05

Images.

POST/v1/images

Upload image

Upload a PNG, JPEG, WebP, GIF, or AVIF image and receive a stable public URL you can use in HTML, apps, or markdown.

Example request
POST /v1/images
curl -X POST https://adjoining-bison-868.convex.site
/v1/images \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: image/png" \
  --data-binary @./screenshot.png
Example response
json response
{
  "id": "img12345",
  "url": "https://adjoining-bison-868.convex.site
/i/img12345",
  "contentType": "image/png",
  "size": 182734
}

Images are immutable once uploaded. Supported content types: image/png, image/jpeg, image/webp, image/gif, image/avif. Max size matches artifact uploads.

GET/v1/images

List images

Retrieve your uploaded images and their stable public URLs.

Example request
GET /v1/images
curl https://adjoining-bison-868.convex.site
/v1/images \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
[
  {
    "id": "img12345",
    "url": "https://adjoining-bison-868.convex.site
/i/img12345",
    "contentType": "image/png",
    "size": 182734,
    "createdAt": 1710900000000,
    "updatedAt": 1710900000000
  }
]
DELETE/v1/images/:id

Delete image

Delete an uploaded image you own. The public image URL will return 404 after deletion.

Example request
DELETE /v1/images/:id
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/images/img12345 \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "id": "img12345",
  "deleted": true
}
§ 06

CSV files.

Using CSV files in apps and artifacts

CSV files are designed for flat table data that should stay in raw text/csv form. Browser code can fetch the public URL and parse the text however it likes.

runtime fetch
const csv = await fetch("https://adjoining-bison-868.convex.site
/c/csv12345").then((r) => r.text());
POST/v1/csv-files

Create CSV file

Store a raw CSV payload exactly as sent and receive a stable public CSV URL.

Example request
POST /v1/csv-files
curl -X POST https://adjoining-bison-868.convex.site
/v1/csv-files \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: text/csv" \
  -H "X-CSV-Title: Inventory Export" \
  --data-binary $'sku,stock\nstarter,12\npro,4\n'
Example response
json response
{
  "id": "csv12345",
  "url": "https://adjoining-bison-868.convex.site
/c/csv12345",
  "contentType": "text/csv",
  "size": 28
}

CSV files are opaque text in v1. They are ideal when browser code or spreadsheet tooling expects flat rows instead of JSON.

GET/v1/csv-files

List CSV files

Retrieve your hosted CSV files and their stable public URLs.

Example request
GET /v1/csv-files
curl https://adjoining-bison-868.convex.site
/v1/csv-files \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
[
  {
    "id": "csv12345",
    "title": "Inventory Export",
    "url": "https://adjoining-bison-868.convex.site
/c/csv12345",
    "contentType": "text/csv",
    "size": 28,
    "createdAt": 1710900000000,
    "updatedAt": 1710900000000
  }
]
PUT/v1/csv-files/:id

Update CSV file

Replace the raw CSV contents for an existing file. The public URL stays the same.

Example request
PUT /v1/csv-files/:id
curl -X PUT https://adjoining-bison-868.convex.site
/v1/csv-files/csv12345 \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: text/csv" \
  -H "X-CSV-Title: Inventory Export v2" \
  --data-binary $'sku,stock\nstarter,10\npro,6\n'
Example response
json response
{
  "id": "csv12345",
  "url": "https://adjoining-bison-868.convex.site
/c/csv12345",
  "contentType": "text/csv",
  "size": 28,
  "updated": true
}
DELETE/v1/csv-files/:id

Delete CSV file

Soft-delete a CSV file. The public CSV URL will return 404 after deletion.

Example request
DELETE /v1/csv-files/:id
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/csv-files/csv12345 \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "id": "csv12345",
  "deleted": true
}
GET/c/:id

Read CSV file

Read a hosted CSV file as public text/csv. This endpoint is meant for runtime fetches from hosted apps and HTML artifacts.

Example request
GET /c/:id
curl https://adjoining-bison-868.convex.site
/c/csv12345
Example response
json response
sku,stock
starter,10
pro,6

Public reads return text/csv with permissive CORS headers, so browser code running on hosted apps can fetch CSV text directly.

§ 07

Datasets.

Using datasets in apps and artifacts

Datasets are written by agents and read at runtime by hosted apps or raw HTML artifacts. The public .json URL is the integration point.

runtime fetch
const data = await fetch("https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json").then((r) => r.json());
POST/v1/datasets

Create dataset

Store a reusable workspace dataset as a JSON object or array and receive a stable public .json URL.

Example request
POST /v1/datasets
curl -X POST https://adjoining-bison-868.convex.site
/v1/datasets \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "inventory",
    "title": "Inventory",
    "data": {
      "rows": [
        { "sku": "starter", "stock": 12 },
        { "sku": "pro", "stock": 4 }
      ]
    }
  }'
Example response
json response
{
  "id": "dat12345",
  "name": "inventory",
  "url": "https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json",
  "created": true
}

Dataset names are workspace-unique URL keys and must use lowercase letters, numbers, underscores, or hyphens. Datasets are intended for hosted apps and HTML artifacts to fetch at runtime.

GET/v1/datasets

List datasets

Retrieve your workspace datasets and their stable public JSON URLs.

Example request
GET /v1/datasets
curl https://adjoining-bison-868.convex.site
/v1/datasets \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
[
  {
    "id": "dat12345",
    "name": "inventory",
    "title": "Inventory",
    "url": "https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json",
    "size": 118,
    "createdAt": 1710900000000,
    "updatedAt": 1710900000000
  }
]
PUT/v1/datasets/:name

Update dataset

Replace the JSON payload for an existing dataset. The public URL stays the same.

Example request
PUT /v1/datasets/:name
curl -X PUT https://adjoining-bison-868.convex.site
/v1/datasets/inventory \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Inventory",
    "data": {
      "rows": [
        { "sku": "starter", "stock": 10 },
        { "sku": "pro", "stock": 6 }
      ]
    }
  }'
Example response
json response
{
  "id": "inventory",
  "name": "inventory",
  "url": "https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json",
  "updated": true
}
DELETE/v1/datasets/:name

Delete dataset

Soft-delete a dataset. The public dataset URL will return 404 after deletion.

Example request
DELETE /v1/datasets/:name
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/datasets/inventory \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "name": "inventory",
  "deleted": true
}
GET/d/:workspaceId/:name.json

Read dataset

Read a dataset as public JSON. This endpoint is meant for runtime fetches from hosted apps and HTML artifacts.

Example request
GET /d/:workspaceId/:name.json
curl https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json
Example response
json response
{
  "rows": [
    { "sku": "starter", "stock": 10 },
    { "sku": "pro", "stock": 6 }
  ]
}

Public reads return JSON with permissive CORS headers, so browser code running on hosted apps can fetch datasets directly.

§ 08

JSON render — structured input.

Instead of raw HTML, send a JSON spec with Content-Type: application/json. The spec is validated and rendered to a full HTML page server-side. Ideal for AI agents and programmatic content generation. See json-render.dev for the full spec.

Spec format
render-spec.json
{
  "root": "page",
  "meta": { "title": "My Page", "style": "body { margin: 0; }" },
  "elements": {
    "page": { "type": "div", "children": ["heading", "content"] },
    "heading": { "type": "h1", "text": "Hello World" },
    "content": { "type": "p", "text": "Built from JSON." }
  }
}
Element fields
FieldTypeDescription
typestringHTML tag name or catalog component name
propsobject?HTML attributes or component props. style accepts objects (camelCase → kebab-case).
childrenstring[]?IDs of child elements. Takes precedence over text.
textstring?Text content (HTML-escaped automatically)
Example · create with JSON
POST /v1/artifacts · json
curl -X POST https://adjoining-bison-868.convex.site
/v1/artifacts \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "root": "r",
    "meta": { "title": "Hello" },
    "elements": {
      "r": { "type": "h1", "text": "Hello from JSON!" }
    }
  }'

Securityscript, iframe, object tags are blocked. Event handler attributes (onclick, etc.) and javascript: URLs are rejected. Max 500 elements, 50 levels of nesting.

§ 09

Multi-page apps.

Host multi-page applications with routes, layouts, and metadata. Apps are defined by a NextAppSpec and server-side rendered with 36 pre-built shadcn/ui components.

Apps share the free-tier quota with artifacts (3 total active items). Specs are stored as JSON (max 512 KB) and rendered via SSR — proper metadata and SEO work out of the box. Upload images to /v1/images first, then reference the returned URLs from app Image components.

POST/v1/apps

Create app

Create a multi-page app from a NextAppSpec. Each route becomes a server-rendered page.

Example request
POST /v1/apps
curl -X POST https://adjoining-bison-868.convex.site
/v1/apps \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "metadata": { "title": "My App" },
    "routes": {
      "/": {
        "page": {
          "root": "h",
          "elements": {
            "h": { "type": "Heading", "props": { "level": "h1", "text": "Hello" }, "children": [] }
          }
        }
      },
      "/about": {
        "page": {
          "root": "p",
          "elements": {
            "p": { "type": "Text", "props": { "text": "About page", "variant": "body" }, "children": [] }
          }
        }
      }
    }
  }'
Example response
json response
{
  "id": "aBcDeFgH",
  "url": "https://www.my-site.io/app/aBcDeFgH",
  "routes": ["/", "/about"]
}

Available component types: Card, Stack, Grid, Table, Heading, Text, Image, Badge, Alert, Button, Input, Textarea, Select, Checkbox, Switch, Tabs, Accordion, Dialog, and more. See GET /v1/apps/catalog/components for the full list, including the built-in Slot layout primitive.

GET/v1/apps

List apps

List all your active apps with their routes and metadata.

Example request
GET /v1/apps
curl https://adjoining-bison-868.convex.site
/v1/apps \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
[
  {
    "id": "aBcDeFgH",
    "title": "My App",
    "url": "https://www.my-site.io/app/aBcDeFgH",
    "routes": ["/", "/about"],
    "createdAt": 1710900000000,
    "updatedAt": 1710900000000
  }
]
PUT/v1/apps/:id

Update app

Replace the spec of an existing app. The URL stays the same.

Example request
PUT /v1/apps/:id
curl -X PUT https://adjoining-bison-868.convex.site
/v1/apps/aBcDeFgH \
  -H "Authorization: Bearer your_artifact_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "routes": { "/": { "page": { "root": "h", "elements": { "h": { "type": "Heading", "props": { "level": "h1", "text": "Updated" }, "children": [] } } } } } }'
Example response
json response
{
  "id": "aBcDeFgH",
  "url": "https://www.my-site.io/app/aBcDeFgH",
  "updated": true
}
DELETE/v1/apps/:id

Delete app

Soft-delete an app you own. Frees up a quota slot.

Example request
DELETE /v1/apps/:id
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/apps/aBcDeFgH \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "id": "aBcDeFgH",
  "deleted": true
}
§ 10

AI integration — catalog.

Endpoints to help AI agents generate valid specs. Use the system prompt and JSON schema to integrate with any LLM.

Use /v1/catalog/* for single-page artifact specs and /v1/apps/catalog/* for multi-page NextAppSpec generation.

GET/v1/catalog/prompt

AI system prompt

Returns a system prompt describing all available components and the expected JSON spec format. Pass this to your LLM as the system message.

Example request
GET /v1/catalog/prompt
curl https://adjoining-bison-868.convex.site
/v1/catalog/prompt \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
You are a UI generator that outputs JSON.

OUTPUT FORMAT (JSONL, RFC 6902 JSON Patch):
...

AVAILABLE COMPONENTS:
- div: HTML <div> element
- h1: HTML <h1> element
- p: HTML <p> element
- img: HTML <img> element (self-closing)
...

Response is text/plain. The prompt includes component descriptions, prop schemas, and output format instructions.

GET/v1/catalog/schema

JSON schema

Returns a JSON Schema for the spec format. Use with structured output APIs (OpenAI, Anthropic, Google).

Example request
GET /v1/catalog/schema
curl "https://adjoining-bison-868.convex.site
/v1/catalog/schema?strict=true" \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "type": "object",
  "properties": {
    "root": { "type": "string" },
    "elements": { "type": "object", "additionalProperties": { ... } }
  },
  "required": ["root", "elements"],
  "additionalProperties": false
}

Add ?strict=true for OpenAI/Anthropic structured output compatibility (additionalProperties: false on all objects).

GET/v1/catalog/components

Component list

Returns all available component types with their metadata.

Example request
GET /v1/catalog/components
curl https://adjoining-bison-868.convex.site
/v1/catalog/components \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "components": [
    { "type": "div", "isVoid": false },
    { "type": "img", "isVoid": true },
    ...
  ],
  "count": 60
}
GET/v1/apps/catalog/prompt

App system prompt

Returns a system prompt for generating multi-page NextAppSpec apps with routes, layouts, metadata, and built-in actions like navigate.

Example request
GET /v1/apps/catalog/prompt
curl https://adjoining-bison-868.convex.site
/v1/apps/catalog/prompt \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
You are a Next.js application generator.

OUTPUT FORMAT (JSONL, RFC 6902 JSON Patch):
...

BUILT-IN ACTIONS:
- setState
- pushState
- removeState
- navigate

RULES:
1. First add /metadata
2. Then add /layouts with Slot
3. Then add /routes
...

Response is text/plain. Use this prompt when asking an LLM to generate a full multi-page app spec instead of a single artifact page.

GET/v1/apps/catalog/schema

App JSON schema

Returns a JSON Schema for NextAppSpec. Use with structured output APIs when generating multi-page apps.

Example request
GET /v1/apps/catalog/schema
curl "https://adjoining-bison-868.convex.site
/v1/apps/catalog/schema?strict=true" \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "type": "object",
  "properties": {
    "metadata": { ... },
    "routes": { "type": "object", "additionalProperties": { ... } },
    "layouts": { "type": "object", "additionalProperties": { ... } },
    "state": { "type": "object" }
  },
  "required": ["routes"],
  "additionalProperties": false
}

Use this instead of /v1/catalog/schema when generating a routed app. Add ?strict=true for structured output compatibility.

GET/v1/apps/catalog/components

App component list

Returns the available app component types for NextAppSpec, including built-in layout primitives.

Example request
GET /v1/apps/catalog/components
curl https://adjoining-bison-868.convex.site
/v1/apps/catalog/components \
  -H "Authorization: Bearer your_artifact_api_key"
Example response
json response
{
  "components": [
    { "type": "Card", "isBuiltIn": false },
    { "type": "Heading", "isBuiltIn": false },
    { "type": "Slot", "isBuiltIn": true }
  ],
  "count": 37
}
§ 11

Error responses.

All errors return JSON with an error field describing what went wrong.

CodeMeaningWhen it happens
401UnauthorizedMissing, invalid, or malformed Authorization header.
402Payment RequiredFree tier artifact limit reached. Upgrade to Pro for more artifacts.
413Payload Too LargeHTML body exceeds the maximum size limit (5 MB).
415Unsupported Media TypeContent-Type is not text/html or application/json.
429Too Many RequestsPer-API-key rate limit exceeded. Check the Retry-After header for when to retry.
Example error response
error body
{
  "error": "Unauthorized"
}
Acceptable use

By using the my-site.io API, you agree to our Acceptable Use Policy. Content that violates the policy may be removed without notice.

API Documentation | my-site.io