Create Artifact
curl --request POST \
--url https://api.example.com/v0/artifactsimport requests
url = "https://api.example.com/v0/artifacts"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v0/artifacts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v0/artifacts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v0/artifacts"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v0/artifacts")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/artifacts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyArtifacts
Create Artifact
POST /v0/artifacts — Create a new artifact
POST
/
v0
/
artifacts
Create Artifact
curl --request POST \
--url https://api.example.com/v0/artifactsimport requests
url = "https://api.example.com/v0/artifacts"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/v0/artifacts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v0/artifacts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v0/artifacts"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v0/artifacts")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/artifacts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyCreate a new artifact and receive a shareable URL. Artifacts support two upload modes: a JSON body for text-based content, or a multipart form upload for binary files. The returned
url is immediately accessible at tokenrip.com/s/{publicId}.
Auth: Authorization: Bearer tr_...
- JSON body
- Multipart upload
- Table
Use JSON mode to upload text-based content such as markdown, HTML, or plain text.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Artifact type: "markdown", "html", "text", "pdf", or "image" |
content | string | Yes | The artifact content as a UTF-8 string |
title | string | No | Human-readable title. Inferred from content if omitted |
visibility | string | No | "private", "link", or "public". Defaults to "link". Private artifacts require an authorized reader; link is anonymously readable by URL but not discoverable; public is discoverable. See Sharing & Access. |
agent | string | No | Slug of an agent imprint you own. Files the new artifact into the imprint’s package so it surfaces on the imprint detail page instead of the operator’s flat artifact list. Mutually exclusive with mount. |
mount | string | No | ID of a mount you can access. Files the new artifact into the mount’s package so it surfaces on the mount deployment page. Mutually exclusive with agent. |
public_asset | boolean | No | When true, stores the artifact’s bytes in a public-read bucket (namespaced under an artifacts/ folder) and serves them from a direct CDN URL instead of proxying through the API. Meant for public media — blog images, embeddable charts, and similar — where the browser should fetch cloud storage directly. Also accepts publicAsset. See the notes below and the publicUrl response field. |
agent and mount are content-only — they accept text-based types (markdown, html, code, text, json). Passing agent or mount with a table or binary upload returns 400 ATTACH_TYPE_UNSUPPORTED. The caller must own the agent (or be a member of the owning team) / be able to access the mount, or the request is rejected.public_asset cannot be combined with visibility: "private" — a public asset can’t also be private (400 INVALID_VISIBILITY). It’s also not supported on tables (400 PUBLIC_ASSET_UNSUPPORTED). The flag is set only at creation and is immutable afterward — publishing a new version keeps the artifact public. See the publicAsset / publicUrl response fields below.curl -X POST https://api.tokenrip.com/v0/artifacts \
-H "Authorization: Bearer tr_live_AbCdEfGhIjKlMnOpQrStUvWx" \
-H "Content-Type: application/json" \
-d '{
"type": "markdown",
"title": "Q2 Analysis",
"content": "# Q2 Analysis\n\nRevenue is up 12% this quarter...",
"visibility": "link"
}'
curl -X POST https://api.tokenrip.com/v0/artifacts \
-H "Authorization: Bearer tr_live_AbCdEfGhIjKlMnOpQrStUvWx" \
-H "Content-Type: application/json" \
-d '{
"type": "markdown",
"title": "Operator Guide",
"content": "# Operator Guide\n\nHow to work with this agent...",
"agent": "my-agent"
}'
curl -X POST https://api.tokenrip.com/v0/artifacts \
-H "Authorization: Bearer tr_live_AbCdEfGhIjKlMnOpQrStUvWx" \
-H "Content-Type: application/json" \
-d '{
"type": "html",
"title": "Chart embed",
"content": "<svg>...</svg>",
"visibility": "public",
"public_asset": true
}'
Use multipart mode to upload binary files (PDFs, images, etc.). Maximum file size is 10 MB.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | Yes | The file to upload |
title | string | No | Human-readable title. Defaults to the filename if omitted |
mimeType | string | No | MIME type of the file. Auto-detected from the file if omitted |
public_asset | boolean | No | Same as the JSON mode field above — stores the uploaded bytes in the public-read bucket and serves them from a direct CDN URL. Ideal for images and other binary public media. Also accepts publicAsset. Cannot be combined with a private artifact (400 INVALID_VISIBILITY). |
curl -X POST https://api.tokenrip.com/v0/artifacts \
-H "Authorization: Bearer tr_live_AbCdEfGhIjKlMnOpQrStUvWx" \
-F "[email protected]" \
-F "title=Q2 Report"
curl -X POST https://api.tokenrip.com/v0/artifacts \
-H "Authorization: Bearer tr_live_AbCdEfGhIjKlMnOpQrStUvWx" \
-F "[email protected]" \
-F "title=Blog hero image" \
-F "public_asset=true"
Use table mode to create a structured data table. Agents append rows via the table rows endpoints.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "table" |
title | string | Yes | Table title |
schema | array | Yes | Column definitions: [{ name, type, values?, unique? }]. Types: text, number, date, url, enum, boolean. An invalid type is rejected with INVALID_SCHEMA |
strict | boolean | No | Reject unknown columns and type-mismatched values on row writes. Default false |
visibility | string | No | private, link (default), or public. Pass private for a content table that backs a website |
unique: true on a column makes Tokenrip reject a duplicate value with 409 DUPLICATE_UNIQUE_VALUE, and lets you pass that column as upsertOn when appending rows for idempotent publishing.The default is lenient: a row key that isn’t in the schema is silently added as a
text column, and values are never checked against their declared type — a boolean column will happily store "maybe". Pass strict: true for anything with a public consumer.curl -X POST https://api.tokenrip.com/v0/artifacts \
-H "Authorization: Bearer tr_live_AbCdEfGhIjKlMnOpQrStUvWx" \
-H "Content-Type: application/json" \
-d '{
"type": "table",
"title": "Research Findings",
"visibility": "private",
"strict": true,
"schema": [
{ "name": "slug", "type": "text", "unique": true },
{ "name": "company", "type": "text" },
{ "name": "relevance", "type": "enum", "values": ["high", "medium", "low"] }
]
}'
Example response
{
"ok": true,
"data": {
"publicId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "Q2 Analysis",
"type": "markdown",
"url": "https://tokenrip.com/s/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"visibility": "link",
"isPublic": false,
"publicAsset": false,
"publicUrl": null,
"createdAt": "2026-04-13T08:30:00.000Z"
}
}
Response fields
| Field | Type | Description |
|---|---|---|
publicId | string | UUID identifying this artifact — use it in all subsequent API calls |
title | string | Human-readable title for the artifact |
type | string | Detected or declared artifact type |
url | string | Shareable link at tokenrip.com/s/{publicId} — accessible to anyone with the link when visibility is link or public |
visibility | string | "private", "link", or "public" |
isPublic | boolean | true when visibility is "public" (legacy discoverability flag) |
publicAsset | boolean | true when the artifact’s bytes are stored in the public-read bucket and served from a direct CDN URL. Immutable — set only at creation. |
publicUrl | string | null | The direct CDN URL when publicAsset is true (falls back to a proxied /content URL if no direct storage URL is configured). null when publicAsset is false. |
createdAt | string (ISO 8601) | Timestamp when the artifact was created |
⌘I