Rendley docs

API reference

Library

Workspace-level media storage. Upload files once and reuse them across projects, list and tag what you have stored, and use chunked uploads for large files.

#List workspace Library assets

One page of the workspace's shared Library, newest first. Each item carries a presigned GET URL that expires: never persist it.

GEThttps://api.rendley.com/v1/workspaces/{workspaceId}/library

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.get(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "items": [
      {
        "created_at": "string",
        "deduplicated": true,
        "download_url": "string",
        "duration": 0,
        "file_hash": "c6c8ec4f9a6fdd9d",
        "file_size": 0,
        "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
        "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
        "mime_type": "string",
        "original_file_name": "string",
        "source": "string",
        "tags": [
          "string"
        ],
        "thumbnail_url": "string",
        "url": "string",
        "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
      }
    ],
    "limit": 0,
    "offset": 0,
    "total": 0
  }
}

#Upload a file into the workspace Library (proxy transport)

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library

Single-call upload: stream the raw file bytes as the request body. The server hashes while storing and returns the completed asset: no separate complete step. Metadata travels in query params. Content-Length is required; files above the proxy cap must use the multipart flow. If identical content already exists in the Library the existing asset is returned with deduplicated=true.

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Rename a workspace Library asset

Update the asset's display name.

PATCHhttps://api.rendley.com/v1/workspaces/{workspaceId}/library/{uploadId}

Don't have one? Create an API key

Body

UploadID is read from the {uploadId} path segment on the public routes; the editor's flat mount still sends it in the body.

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID", {
  method: "PATCH",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "<name>"
  }),
});
const { data } = await res.json();
curl -X PATCH "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "<name>"
  }'
import requests

res = requests.patch(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "name": "<name>"
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["name" => "<name>"]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "name": "<name>"
}`)
	req, _ := http.NewRequest("PATCH", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { name: "<name>" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Delete a workspace Library asset

Remove the asset and refund its storage. Does not touch any project copies bridged from it.

DELETEhttps://api.rendley.com/v1/workspaces/{workspaceId}/library/{uploadId}

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID", {
  method: "DELETE",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl -X DELETE "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.delete(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID")
req = Net::HTTP::Delete.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

#Bridge a Library asset into a project

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/{uploadId}/add-to-project

Server-side copy of the asset into the project's media storage plus a role=staged upload row: the editor adopts it on reference instead of re-uploading bytes. Returns the project-side upload (media_id, file_hash, presigned URL).

Don't have one? Create an API key

Body
const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/add-to-project", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "project_id": "<project_id>"
  }),
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/add-to-project" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "project_id": "<project_id>"
  }'
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/add-to-project",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "project_id": "<project_id>"
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/add-to-project");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["project_id" => "<project_id>"]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "project_id": "<project_id>"
}`)
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/add-to-project", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/add-to-project")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { project_id: "<project_id>" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "role": "string",
    "status": "string",
    "storage_url": "string"
  }
}

#Update a workspace Library asset's tags

Replace the asset's tag set (used to classify library media).

PATCHhttps://api.rendley.com/v1/workspaces/{workspaceId}/library/{uploadId}/tags

Don't have one? Create an API key

Body

UploadID is read from the {uploadId} path segment on the public routes; the editor's flat mount still sends it in the body.

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/tags", {
  method: "PATCH",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "tags": [
      "string"
    ],
    "upload_id": "<upload_id>"
  }),
});
const { data } = await res.json();
curl -X PATCH "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/tags" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": [
      "string"
    ],
    "upload_id": "<upload_id>"
  }'
import requests

res = requests.patch(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/tags",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "tags": [
            "string"
        ],
        "upload_id": "<upload_id>"
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/tags");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["tags" => ["string"], "upload_id" => "<upload_id>"]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "tags": [
    "string"
  ],
  "upload_id": "<upload_id>"
}`)
	req, _ := http.NewRequest("PATCH", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/tags", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/UPLOAD_ID/tags")
req = Net::HTTP::Patch.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { tags: ["string"], upload_id: "<upload_id>" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Abort a chunked server-hashed Library upload

Discards the in-progress session, its stored parts, and the pending asset row.

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/chunked/{uploadId}/abort

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/abort", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/abort" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/abort",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/abort");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/abort", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/abort")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

#Complete a chunked server-hashed Library upload

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/chunked/{uploadId}/complete

Assembles the parts and finalizes the asset with the server-computed hash. Requires every declared byte to have arrived. Dedup-aware: identical existing content is returned with deduplicated=true.

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/complete", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/complete" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/complete",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/complete");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/complete", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/complete")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Upload one part of a chunked Library upload

PUThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/chunked/{uploadId}/parts/{partNumber}

Raw part bytes as the request body. Parts must be sent strictly in order (409 CHUNK_OUT_OF_ORDER carries the expected part number); only the final part may be under the minimum part size. Content-Length is required.

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/parts/PART_NUMBER", {
  method: "PUT",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl -X PUT "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/parts/PART_NUMBER" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.put(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/parts/PART_NUMBER",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/parts/PART_NUMBER");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("PUT", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/parts/PART_NUMBER", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/UPLOAD_ID/parts/PART_NUMBER")
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "next_part": 0,
    "received_bytes": 0
  }
}

#Start a chunked server-hashed Library upload

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/chunked/initiate

Hashless large-file transport for API/MCP clients that cannot compute XXH64: parts are PUT to the API strictly in order, the server hashes them incrementally while forwarding to storage, and the hash exists at complete: computed server-side. Files under the proxy cap should use the single-call proxy upload instead.

Don't have one? Create an API key

Body
const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/initiate", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "file_size": 0
  }),
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/initiate" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_size": 0
  }'
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/initiate",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "file_size": 0
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/initiate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["file_size" => 0]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "file_size": 0
}`)
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/initiate", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/chunked/initiate")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { file_size: 0 }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "part_size_max": 0,
    "part_size_min": 0,
    "upload_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Add a project's media file to the workspace Library

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/from-project

Copies the media (resolved by project ID + content hash) into the Library server-side: no bytes transit the client. Returns the existing asset with deduplicated=true when identical content is already in the Library.

Don't have one? Create an API key

Body
const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/from-project", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "file_hash": "<file_hash>",
    "project_id": "<project_id>"
  }),
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/from-project" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_hash": "<file_hash>",
    "project_id": "<project_id>"
  }'
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/from-project",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "file_hash": "<file_hash>",
        "project_id": "<project_id>"
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/from-project");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["file_hash" => "<file_hash>", "project_id" => "<project_id>"]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "file_hash": "<file_hash>",
  "project_id": "<project_id>"
}`)
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/from-project", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/from-project")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { file_hash: "<file_hash>", project_id: "<project_id>" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Abort a chunked Library upload

Discard an in-progress multipart upload and its pending asset row.

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/multipart/abort

Don't have one? Create an API key

Body
const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/abort", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "s3_upload_id": "<s3_upload_id>",
    "upload_id": "<upload_id>"
  }),
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/abort" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "s3_upload_id": "<s3_upload_id>",
    "upload_id": "<upload_id>"
  }'
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/abort",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "s3_upload_id": "<s3_upload_id>",
        "upload_id": "<upload_id>"
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/abort");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["s3_upload_id" => "<s3_upload_id>", "upload_id" => "<upload_id>"]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "s3_upload_id": "<s3_upload_id>",
  "upload_id": "<upload_id>"
}`)
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/abort", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/abort")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { s3_upload_id: "<s3_upload_id>", upload_id: "<upload_id>" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

#Complete a chunked Library upload

Assemble the uploaded parts into the final object and mark the asset complete. Quota is charged from the size the bucket actually stored.

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/multipart/complete

Don't have one? Create an API key

Body
partsrequiredobject[]
const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/complete", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "parts": [
      {
        "etag": "string",
        "part_number": 0
      }
    ],
    "s3_upload_id": "<s3_upload_id>",
    "upload_id": "<upload_id>"
  }),
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/complete" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "parts": [
      {
        "etag": "string",
        "part_number": 0
      }
    ],
    "s3_upload_id": "<s3_upload_id>",
    "upload_id": "<upload_id>"
  }'
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/complete",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "parts": [
            {
                "etag": "string",
                "part_number": 0
            }
        ],
        "s3_upload_id": "<s3_upload_id>",
        "upload_id": "<upload_id>"
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/complete");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["parts" => [["etag" => "string", "part_number" => 0]], "s3_upload_id" => "<s3_upload_id>", "upload_id" => "<upload_id>"]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "parts": [
    {
      "etag": "string",
      "part_number": 0
    }
  ],
  "s3_upload_id": "<s3_upload_id>",
  "upload_id": "<upload_id>"
}`)
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/complete", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/complete")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { parts: [{ etag: "string", part_number: 0 }], s3_upload_id: "<s3_upload_id>", upload_id: "<upload_id>" }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Start a chunked Library upload (large-file transport)

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/multipart/initiate

For files above the proxy cap: records a pending asset and returns presigned part URLs pointing straight at object storage. Finish with the multipart complete call. When identical content already exists in the Library the response carries existing (deduplicated=true) instead of an upload session: skip the transfer.

Don't have one? Create an API key

Body

FileHash is required: multipart bytes go client→bucket, so the client is the only party that ever holds the full stream: every completed library row must carry its content hash (XXH64, 16 hex chars).

Source provenance; clients may claim "uploaded" (default) or "export".

Transient uploads are scratch input for an AI job: never listed as a Library asset, unmetered, removed by the daily stale-upload sweep. Reference by upload id only.

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/initiate", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    "file_hash": "<file_hash>",
    "file_size": 0,
    "part_count": 0
  }),
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/initiate" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_hash": "<file_hash>",
    "file_size": 0,
    "part_count": 0
  }'
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/initiate",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "file_hash": "<file_hash>",
        "file_size": 0,
        "part_count": 0
    },
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/initiate");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(["file_hash" => "<file_hash>", "file_size" => 0, "part_count" => 0]));

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
	"bytes"
)

func main() {
	body := bytes.NewBufferString(`{
  "file_hash": "<file_hash>",
  "file_size": 0,
  "part_count": 0
}`)
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/initiate", body)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/multipart/initiate")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"
req["Content-Type"] = "application/json"
req.body = { file_hash: "<file_hash>", file_size: 0, part_count: 0 }.to_json

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "existing": {
      "created_at": "string",
      "deduplicated": true,
      "download_url": "string",
      "duration": 0,
      "file_hash": "c6c8ec4f9a6fdd9d",
      "file_size": 0,
      "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
      "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
      "mime_type": "string",
      "original_file_name": "string",
      "source": "string",
      "tags": [
        "string"
      ],
      "thumbnail_url": "string",
      "url": "string",
      "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
    },
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "presigned_urls": [
      {
        "part_number": 0,
        "url": "string"
      }
    ],
    "s3_upload_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "upload_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}

#Upload scratch input for an AI job

POSThttps://api.rendley.com/v1/workspaces/{workspaceId}/library/transient

Stream raw file bytes to be used as an AI job input without adding them to the Library: the file is never listed as an asset, charges no storage, and is removed by the daily stale-upload sweep. Reference it in the job's params by the returned id only. Content-Length is required.

Don't have one? Create an API key

const res = await fetch("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/transient", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
const { data } = await res.json();
curl -X POST "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/transient" \
  -H "Authorization: Bearer YOUR_API_KEY"
import requests

res = requests.post(
    "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/transient",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()["data"]
$ch = curl_init("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/transient");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer YOUR_API_KEY"]);

$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true)["data"];
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	req, _ := http.NewRequest("POST", "https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/transient", nil)
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	res, _ := http.DefaultClient.Do(req)
	defer res.Body.Close()
	b, _ := io.ReadAll(res.Body)
	fmt.Println(string(b))
}
require "net/http"
require "json"

uri = URI("https://api.rendley.com/v1/workspaces/WORKSPACE_ID/library/transient")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer YOUR_API_KEY"

res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body)["data"]

Response 200

{
  "data": {
    "created_at": "string",
    "deduplicated": true,
    "download_url": "string",
    "duration": 0,
    "file_hash": "c6c8ec4f9a6fdd9d",
    "file_size": 0,
    "id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70",
    "media_id": "c448b6e3-2b78-4bda-b369-d1afc6aec07f",
    "mime_type": "string",
    "original_file_name": "string",
    "source": "string",
    "tags": [
      "string"
    ],
    "thumbnail_url": "string",
    "url": "string",
    "workspace_id": "3f0d5a4e-3d2a-4c1f-9b3e-2a1c4d5e6f70"
  }
}