Skip to content

File API

The File API lets external services and integrations create, read, and list files (assets) in the Runnit asset library, so automated work can build on files already produced for the same brief or project.

Use the asset ID to identify a file. Storage URLs can change when its content is replaced, so fetch current metadata after an update instead of constructing a URL from the filename. See the Assets API for updates and version restoration.

A rejected save can return HTTP 413 with KNOWLEDGE_CONTENT_CAPACITY_EXCEEDED when retained file history has reached its limit, or KNOWLEDGE_CONTENT_TOO_LARGE when the content is too large. The file change is not saved. Contact support for a history capacity failure; reduce the content for a size failure.

Every request must include both:

  • organizationId: the organisation you are acting on behalf of.
  • organizationApiKey: the signed key supplied in your agent payload.

Send them as headers:

X-Organization-Id: <your-organization-id>
X-Organization-Api-Key: <your-agent-api-key>

or embed them in the JSON body (for POST). Credentials in the query string are ignored, so a GET must send the headers.

Requests missing either value return 401 Unauthorized. If the credentials do not match the organisation you are acting for, the API returns 403 Forbidden. Never log or echo the API key.

When you receive a task, the payload includes an existingFiles array containing files created by all agents and jobs for the same brief or project, parent brief files, files from other agent types, earlier versions of your own agent, and human uploads. Use it to maintain consistency and avoid duplicating research.

Each entry provides direct access details so you can load content without calling the File API:

FieldTypeDescription
idstringAsset identifier.
fileNamestringFile name, including extension.
fileTypestringResolved type (e.g. markdown, image, video).
descriptionstringHuman-readable description.
createdByAgentTypestringAgent type that produced the file.
fileSizenumberSize in bytes.
urlstringPrimary access URL for the file content.
isRemoteUrlbooleantrue when url points to an external host (e.g. a hosted video).
storageProviderstringWhere the asset is stored.
apiUrlstringMetadata endpoint for the asset.

For local files, fetch url and read the response as text. For remote files (isRemoteUrl: true), the url points directly to the hosted file and can be embedded as-is. When you need more metadata, fetch apiUrl.

POST /api/assets
FieldTypeRequiredDescription
fileNamestringYesFile name, including extension.
fileExtensionstringYesFile extension (e.g. md, html, json).
contentstringYesFile content. For remote files, the URL to the hosted file.
entityLinksarrayYesAt least one { entityType, entityId } link (e.g. job, organization).
descriptionstringNoDescription stored on the asset.
metadataobjectNoAdditional metadata.
createdByAgentTypestringNoAgent type for tracking.
isRemoteUrlbooleanNoSet true when content holds a URL to a remotely hosted file. Defaults to false.

Use isRemoteUrl: true for large media hosted on external CDNs (such as generated videos) where you store a URL rather than the file itself. Use false (or omit it) for text, markdown, HTML, JSON, and images stored directly.

Terminal window
curl -X POST https://api.runnit.io/api/assets \
-H "Content-Type: application/json" \
-H "X-Organization-Id: <your-organization-id>" \
-H "X-Organization-Api-Key: <your-agent-api-key>" \
-d '{
"fileName": "video_script_final.md",
"fileExtension": "md",
"content": "# Video Script\n\nContent...",
"description": "Main video script",
"createdByAgentType": "copywriter",
"entityLinks": [
{ "entityType": "job", "entityId": "your-job-id" }
]
}'
{
"success": true,
"asset": {
"id": "asset-uuid",
"jobId": "job-uuid",
"fileName": "video_script_final.md",
"fileType": "markdown",
"fileExtension": "md",
"mimeType": "text/markdown",
"fileSize": 1234,
"storageProvider": "aws",
"createdAt": "2025-10-06T12:00:00Z"
}
}
GET /api/assets/file?entityType=job&entityId={entityId}&fileName={fileName}
{
"success": true,
"asset": {
"id": "asset-uuid",
"jobId": "job-uuid",
"fileName": "video_script_final.md",
"fileType": "markdown",
"content": "# My Content\n\n...",
"description": "Optional description",
"metadata": {},
"createdAt": "2025-10-06T12:00:00Z",
"version": 1
}
}
GET /api/assets?entityType=job&entityId={entityId}
{
"success": true,
"assets": [
{
"id": "asset-1",
"fileName": "script.md",
"fileType": "markdown",
"fileExtension": "md",
"fileSize": 1234,
"description": "Main script",
"createdAt": "2025-10-06T12:00:00Z",
"version": 1
}
]
}

The asset library also exposes search, tagging, folders, insights, and version history. Prefer the MCP search_assets and read_file tools where available.

GET /api/assets/search?q={text}&entityType=organization&entityId={entityId}

q is required free text (minimum 3 characters). Optional filters include organizationId, entityType, entityId, folderId, tagIds, and limit. Results are similarity-scored chunks with the matched text and description.

POST /api/assets/{assetId}/tags
DELETE /api/assets/{assetId}/tags/{tagId}

Link or unlink curated tags on an asset. The POST body takes { "tagIds": ["uuid", ...] }.

GET /api/assets/folders?ownerEntityType=organization&ownerEntityId={entityId}
POST /api/assets/folders
POST /api/assets/{assetId}/folders

Each organisation, project, and job has a root folder tree for grouping logos, guidelines, and campaign assets.

GET /api/assets/{assetId}/insights
POST /api/assets/{assetId}/reindex

insights returns tags, folders, a summary excerpt, search status, and the last indexed timestamp. reindex regenerates the asset’s chunks and embeddings.

GET /api/assets/{assetId}/versions
POST /api/assets/{assetId}/versions/{versionId}/restore

Every update snapshots a version. Restoring moves the asset back to that snapshot.

Use lowercase names with underscores that describe the content, and standard extensions. Default to Markdown (.md) for text-based content.

ExtensionTypeUse for
.mdMarkdownScripts, blog posts, articles, documentation
.htmlHTMLEmail templates, web pages
.txtTextSimple copy, notes
.jsonJSONData, configurations
.csvCSVTables, lists
.svgSVGVector graphics
.jpg, .pngImageImages

Good names: video_script_final.md, social_linkedin_post_1.md, ad_copy_google_variant_a.md. Avoid generic names like file1.md or output.md.

Use the public Assets API with your rnk_ key, or the MCP file tools with an ordinary user-generated MCP credential. Each credential stays bound to its organisation, even if you belong to several workspaces.

Direct file reads require permission to view assets. Private files also require uploader, linked conversation-owner, or authorising organisation owner/admin access. Finance documents retain their Finance permissions. Organisation API keys and internal sessions limited to a job, client or tool set continue to reject private-file reads.

Receipt reads require a user with current access to the expense. Organisation-only credentials cannot read or analyse them. Use your generated user token through the Assets API or an authorised MCP file tool. Receipt downloads use authenticated application addresses, and public document-viewer links and shared copies are refused.

SVG content may be raw XML or base64 file bytes. Read isBinary to identify the representation and fileSize for the actual byte count. Downloads return the original image bytes, including earlier uploads. Use the returned SVG URL with your file credentials. See Assets API for update, restore and download details.