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.
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.
- Agent-first path: call
POST /v1/workspacesto get an unclaimed workspace key and claim URL instantly. - Human-claim path: visit the claim URL and sign in with GitHub to unlock claimed-workspace capabilities such as apps.
- Sign in with GitHub to create or access your dashboard account directly.
- Open the dashboard after sign-in.
- Generate your API key from the dashboard. It is displayed once — copy it and store it securely.
- If you lose your key, regenerate it from the dashboard. Regenerating invalidates the old key.
Authorization: Bearer your_artifact_api_keyAPI 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.
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.
curl https://www.my-site.io/skill.mdReturns 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.
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.
X-Artifact-Title: My Dashboard
X-Client-Name: codex-cli
X-Client-Version: 1.2.3
X-Run-Id: run_abc123X-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.
Artifacts.
/v1/artifactsCreate artifact
Upload raw HTML and receive a live public URL. The HTML is stored and immediately accessible.
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>'{
"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.
/v1/artifacts/:idUpdate artifact
Replace the HTML content of an existing artifact you own. The public URL stays the same.
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>'{
"id": "abc123",
"url": "https://adjoining-bison-868.convex.site
/a/abc123",
"updated": true
}/v1/artifactsList artifacts
Retrieve a list of all your active artifacts with their metadata.
curl https://adjoining-bison-868.convex.site
/v1/artifacts \
-H "Authorization: Bearer your_artifact_api_key"[
{
"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.
/v1/artifacts/:idDelete artifact
Soft-delete an artifact you own. The public URL will return 404 after deletion.
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/artifacts/abc123 \
-H "Authorization: Bearer your_artifact_api_key"{
"id": "abc123",
"deleted": true
}Deleting an artifact frees up your quota slot on the free tier.
Images.
/v1/imagesUpload image
Upload a PNG, JPEG, WebP, GIF, or AVIF image and receive a stable public URL you can use in HTML, apps, or markdown.
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{
"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.
/v1/imagesList images
Retrieve your uploaded images and their stable public URLs.
curl https://adjoining-bison-868.convex.site
/v1/images \
-H "Authorization: Bearer your_artifact_api_key"[
{
"id": "img12345",
"url": "https://adjoining-bison-868.convex.site
/i/img12345",
"contentType": "image/png",
"size": 182734,
"createdAt": 1710900000000,
"updatedAt": 1710900000000
}
]/v1/images/:idDelete image
Delete an uploaded image you own. The public image URL will return 404 after deletion.
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/images/img12345 \
-H "Authorization: Bearer your_artifact_api_key"{
"id": "img12345",
"deleted": true
}CSV files.
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.
const csv = await fetch("https://adjoining-bison-868.convex.site
/c/csv12345").then((r) => r.text());/v1/csv-filesCreate CSV file
Store a raw CSV payload exactly as sent and receive a stable public CSV URL.
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'{
"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.
/v1/csv-filesList CSV files
Retrieve your hosted CSV files and their stable public URLs.
curl https://adjoining-bison-868.convex.site
/v1/csv-files \
-H "Authorization: Bearer your_artifact_api_key"[
{
"id": "csv12345",
"title": "Inventory Export",
"url": "https://adjoining-bison-868.convex.site
/c/csv12345",
"contentType": "text/csv",
"size": 28,
"createdAt": 1710900000000,
"updatedAt": 1710900000000
}
]/v1/csv-files/:idUpdate CSV file
Replace the raw CSV contents for an existing file. The public URL stays the same.
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'{
"id": "csv12345",
"url": "https://adjoining-bison-868.convex.site
/c/csv12345",
"contentType": "text/csv",
"size": 28,
"updated": true
}/v1/csv-files/:idDelete CSV file
Soft-delete a CSV file. The public CSV URL will return 404 after deletion.
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/csv-files/csv12345 \
-H "Authorization: Bearer your_artifact_api_key"{
"id": "csv12345",
"deleted": true
}/c/:idRead CSV file
Read a hosted CSV file as public text/csv. This endpoint is meant for runtime fetches from hosted apps and HTML artifacts.
curl https://adjoining-bison-868.convex.site
/c/csv12345sku,stock
starter,10
pro,6Public reads return text/csv with permissive CORS headers, so browser code running on hosted apps can fetch CSV text directly.
Datasets.
Datasets are written by agents and read at runtime by hosted apps or raw HTML artifacts. The public .json URL is the integration point.
const data = await fetch("https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json").then((r) => r.json());/v1/datasetsCreate dataset
Store a reusable workspace dataset as a JSON object or array and receive a stable public .json URL.
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 }
]
}
}'{
"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.
/v1/datasetsList datasets
Retrieve your workspace datasets and their stable public JSON URLs.
curl https://adjoining-bison-868.convex.site
/v1/datasets \
-H "Authorization: Bearer your_artifact_api_key"[
{
"id": "dat12345",
"name": "inventory",
"title": "Inventory",
"url": "https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json",
"size": 118,
"createdAt": 1710900000000,
"updatedAt": 1710900000000
}
]/v1/datasets/:nameUpdate dataset
Replace the JSON payload for an existing dataset. The public URL stays the same.
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 }
]
}
}'{
"id": "inventory",
"name": "inventory",
"url": "https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json",
"updated": true
}/v1/datasets/:nameDelete dataset
Soft-delete a dataset. The public dataset URL will return 404 after deletion.
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/datasets/inventory \
-H "Authorization: Bearer your_artifact_api_key"{
"name": "inventory",
"deleted": true
}/d/:workspaceId/:name.jsonRead dataset
Read a dataset as public JSON. This endpoint is meant for runtime fetches from hosted apps and HTML artifacts.
curl https://adjoining-bison-868.convex.site
/d/ws_123/inventory.json{
"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.
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.
{
"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." }
}
}| Field | Type | Description |
|---|---|---|
| type | string | HTML tag name or catalog component name |
| props | object? | HTML attributes or component props. style accepts objects (camelCase → kebab-case). |
| children | string[]? | IDs of child elements. Takes precedence over text. |
| text | string? | Text content (HTML-escaped automatically) |
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!" }
}
}'script, iframe, object tags are blocked. Event handler attributes (onclick, etc.) and javascript: URLs are rejected. Max 500 elements, 50 levels of nesting.
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.
/v1/appsCreate app
Create a multi-page app from a NextAppSpec. Each route becomes a server-rendered page.
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": [] }
}
}
}
}
}'{
"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.
/v1/appsList apps
List all your active apps with their routes and metadata.
curl https://adjoining-bison-868.convex.site
/v1/apps \
-H "Authorization: Bearer your_artifact_api_key"[
{
"id": "aBcDeFgH",
"title": "My App",
"url": "https://www.my-site.io/app/aBcDeFgH",
"routes": ["/", "/about"],
"createdAt": 1710900000000,
"updatedAt": 1710900000000
}
]/v1/apps/:idUpdate app
Replace the spec of an existing app. The URL stays the same.
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": [] } } } } } }'{
"id": "aBcDeFgH",
"url": "https://www.my-site.io/app/aBcDeFgH",
"updated": true
}/v1/apps/:idDelete app
Soft-delete an app you own. Frees up a quota slot.
curl -X DELETE https://adjoining-bison-868.convex.site
/v1/apps/aBcDeFgH \
-H "Authorization: Bearer your_artifact_api_key"{
"id": "aBcDeFgH",
"deleted": true
}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.
/v1/catalog/promptAI 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.
curl https://adjoining-bison-868.convex.site
/v1/catalog/prompt \
-H "Authorization: Bearer your_artifact_api_key"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.
/v1/catalog/schemaJSON schema
Returns a JSON Schema for the spec format. Use with structured output APIs (OpenAI, Anthropic, Google).
curl "https://adjoining-bison-868.convex.site
/v1/catalog/schema?strict=true" \
-H "Authorization: Bearer your_artifact_api_key"{
"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).
/v1/catalog/componentsComponent list
Returns all available component types with their metadata.
curl https://adjoining-bison-868.convex.site
/v1/catalog/components \
-H "Authorization: Bearer your_artifact_api_key"{
"components": [
{ "type": "div", "isVoid": false },
{ "type": "img", "isVoid": true },
...
],
"count": 60
}/v1/apps/catalog/promptApp system prompt
Returns a system prompt for generating multi-page NextAppSpec apps with routes, layouts, metadata, and built-in actions like navigate.
curl https://adjoining-bison-868.convex.site
/v1/apps/catalog/prompt \
-H "Authorization: Bearer your_artifact_api_key"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.
/v1/apps/catalog/schemaApp JSON schema
Returns a JSON Schema for NextAppSpec. Use with structured output APIs when generating multi-page apps.
curl "https://adjoining-bison-868.convex.site
/v1/apps/catalog/schema?strict=true" \
-H "Authorization: Bearer your_artifact_api_key"{
"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.
/v1/apps/catalog/componentsApp component list
Returns the available app component types for NextAppSpec, including built-in layout primitives.
curl https://adjoining-bison-868.convex.site
/v1/apps/catalog/components \
-H "Authorization: Bearer your_artifact_api_key"{
"components": [
{ "type": "Card", "isBuiltIn": false },
{ "type": "Heading", "isBuiltIn": false },
{ "type": "Slot", "isBuiltIn": true }
],
"count": 37
}Error responses.
All errors return JSON with an error field describing what went wrong.
| Code | Meaning | When it happens |
|---|---|---|
| 401 | Unauthorized | Missing, invalid, or malformed Authorization header. |
| 402 | Payment Required | Free tier artifact limit reached. Upgrade to Pro for more artifacts. |
| 413 | Payload Too Large | HTML body exceeds the maximum size limit (5 MB). |
| 415 | Unsupported Media Type | Content-Type is not text/html or application/json. |
| 429 | Too Many Requests | Per-API-key rate limit exceeded. Check the Retry-After header for when to retry. |
{
"error": "Unauthorized"
}By using the my-site.io API, you agree to our Acceptable Use Policy. Content that violates the policy may be removed without notice.