Create a file
/assetsCosts 2 rate-limit points · Rate limits
Add a file to the library, as the Files page's Add does. type is file (a stored upload), link (an absolute url, such as https://…, to an external page or download) or licence_key (a pool of keys). A file answers with upload: {url, method, headers, expires_at}; PUT the file's bytes there within the hour, nothing else is needed. An AI assistant that can't send the bytes itself (in a chat) should ask the merchant to upload the file on the Files page instead. watermark.enabled applies to PDFs; licence_keys.autogenerate mints keys on demand, licence_keys.tags names the pools the file draws from.
A stored file counts against the plan's file and storage quota from this call (402-style quota errors come back as 422 with code). Nothing is linked to a product until POST /digital_products/:id/files/attach.
Also searched asupload a fileadd a fileadd a linkcreate a licence key filenew fileadd a download
Request body
typestringRequiredExample:filenamestringExample:Beginner's GuideurlanyfileobjectShow 3 child attributesHide child attributes
filenamestringExample:guide.pdfbyte_sizeintegerExample:1048576content_typestringExample:application/pdf
watermarkobjectShow 1 child attributeHide child attributes
enabledbooleanExample:true
licence_keysany
Errors
Missing or invalid API key.
The request failed validation, or sent a key the action does not take (code: "unknown_parameters" with unknown and accepted). Nothing was saved.
Rate limited. Cost-weighted per API key, shared with API v1: a read costs 1 point, a write 2, 40 points per fixed 60-second window. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix time the window ends); a 429 adds Retry-After (seconds), retry_after, retryable: true and a next_step in the body. A 429 did nothing: wait retry_after seconds, then send the same request again. The budget is per key, so every tool or script using the key shares it; prefer one list call with per_page over many single reads.
Every error has the same shape: see Errors.
Answers with an upload URL; PUT the file's bytes there within the hour.
curl -X POST "https://app.filemonk.io/api/v2/external/assets" \
-H "X-Auth-Token: $FILEMONK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "file",
"name": "Beginner'\''s Guide",
"file": {
"filename": "guide.pdf",
"byte_size": 1048576,
"content_type": "application/pdf"
},
"watermark": {
"enabled": true
}
}'const res = await fetch("https://app.filemonk.io/api/v2/external/assets", {
method: "POST",
headers: {
"X-Auth-Token": process.env.FILEMONK_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"type": "file",
"name": "Beginner's Guide",
"file": {
"filename": "guide.pdf",
"byte_size": 1048576,
"content_type": "application/pdf"
},
"watermark": {
"enabled": true
}
}),
});
const data = await res.json();import os
import requests
res = requests.post(
"https://app.filemonk.io/api/v2/external/assets",
headers={"X-Auth-Token": os.environ["FILEMONK_API_KEY"]},
json={
"type": "file",
"name": "Beginner's Guide",
"file": {
"filename": "guide.pdf",
"byte_size": 1048576,
"content_type": "application/pdf"
},
"watermark": {
"enabled": True
}
},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.filemonk.io/api/v2/external/assets")
req = Net::HTTP::Post.new(uri, "X-Auth-Token" => ENV["FILEMONK_API_KEY"], "Content-Type" => "application/json")
req.body = {
type: "file",
name: "Beginner's Guide",
file: {
filename: "guide.pdf",
byte_size: 1048576,
content_type: "application/pdf"
},
watermark: {
enabled: true
}
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"id": "e2b7727e-45ad-42b7-b842-cc4615205b10",
"type": "file",
"name": "guide.pdf",
"filename": "guide.pdf",
"extension": "pdf",
"content_type": "application/pdf",
"byte_size": 1048576,
"url": null,
"url_expires_at": null,
"watermark": {
"enabled": true
},
"licence_keys": {
"autogenerate": false,
"tags": []
},
"usage": {
"digital_products_count": 0,
"orders_count": 0
},
"digital_products": [],
"recent_orders": [],
"created_at": "2026-10-30T16:49:38Z",
"updated_at": "2026-10-30T16:49:38Z",
"upload": {
"url": "https://files.filemonk.io/uploads/5f3e9c1a/guide.pdf?X-Amz-Expires=3600&X-Amz-Signature=3f6c…",
"method": "PUT",
"headers": {
"Content-Type": "application/pdf"
},
"expires_at": "2026-10-31T00:10:00Z"
}
}{
"id": "e2b7727e-45ad-42b7-b842-cc4615205b10",
"type": "file",
"name": "guide.pdf",
"filename": "guide.pdf",
"extension": "pdf",
"content_type": "application/pdf",
"byte_size": 1048576,
"url": null,
"url_expires_at": null,
"watermark": {
"enabled": true
},
"licence_keys": {
"autogenerate": false,
"tags": []
},
"usage": {
"digital_products_count": 0,
"orders_count": 0
},
"digital_products": [],
"recent_orders": [],
"created_at": "2026-10-30T16:49:38Z",
"updated_at": "2026-10-30T16:49:38Z",
"upload": {
"url": "https://files.filemonk.io/uploads/5f3e9c1a/guide.pdf?X-Amz-Expires=3600&X-Amz-Signature=3f6c…",
"method": "PUT",
"headers": {
"Content-Type": "application/pdf"
},
"expires_at": "2026-10-31T00:10:00Z"
}
}{
"errors": [
"Invalid API key"
]
}{
"errors": [
"access.download_limit_count must be an integer of at least 0"
],
"field_errors": {
"access.download_limit_count": [
"must be an integer of at least 0"
]
}
}{
"errors": [
"You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
],
"code": "rate_limited",
"retry_after": 12,
"error": "Rate limit exceeded",
"message": "You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
}Nothing is uploaded: buyers get the link.
curl -X POST "https://app.filemonk.io/api/v2/external/assets" \
-H "X-Auth-Token: $FILEMONK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "link",
"name": "Watercolour course videos",
"url": "https://cdn.example.com/watercolour-course-videos.zip"
}'const res = await fetch("https://app.filemonk.io/api/v2/external/assets", {
method: "POST",
headers: {
"X-Auth-Token": process.env.FILEMONK_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"type": "link",
"name": "Watercolour course videos",
"url": "https://cdn.example.com/watercolour-course-videos.zip"
}),
});
const data = await res.json();import os
import requests
res = requests.post(
"https://app.filemonk.io/api/v2/external/assets",
headers={"X-Auth-Token": os.environ["FILEMONK_API_KEY"]},
json={
"type": "link",
"name": "Watercolour course videos",
"url": "https://cdn.example.com/watercolour-course-videos.zip"
},
)
data = res.json()require "net/http"
require "json"
uri = URI("https://app.filemonk.io/api/v2/external/assets")
req = Net::HTTP::Post.new(uri, "X-Auth-Token" => ENV["FILEMONK_API_KEY"], "Content-Type" => "application/json")
req.body = {
type: "link",
name: "Watercolour course videos",
url: "https://cdn.example.com/watercolour-course-videos.zip"
}.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
data = JSON.parse(res.body){
"id": "e2b7727e-45ad-42b7-b842-cc4615205b10",
"type": "link",
"name": "Watercolour course videos",
"filename": "watercolour-course-videos.zip",
"extension": "zip",
"content_type": "application/zip",
"byte_size": 0,
"url": "https://cdn.example.com/watercolour-course-videos.zip",
"url_expires_at": null,
"watermark": {
"enabled": false
},
"licence_keys": {
"autogenerate": false,
"tags": []
},
"usage": {
"digital_products_count": 0,
"orders_count": 0
},
"digital_products": [],
"recent_orders": [],
"created_at": "2026-10-30T16:49:38Z",
"updated_at": "2026-10-30T16:49:38Z",
"upload": {
"url": "https://files.filemonk.io/uploads/5f3e9c1a/guide.pdf?X-Amz-Expires=3600&X-Amz-Signature=3f6c…",
"method": "PUT",
"headers": {
"Content-Type": "application/pdf"
},
"expires_at": "2026-10-31T00:10:00Z"
}
}{
"id": "e2b7727e-45ad-42b7-b842-cc4615205b10",
"type": "link",
"name": "Watercolour course videos",
"filename": "watercolour-course-videos.zip",
"extension": "zip",
"content_type": "application/zip",
"byte_size": 0,
"url": "https://cdn.example.com/watercolour-course-videos.zip",
"url_expires_at": null,
"watermark": {
"enabled": false
},
"licence_keys": {
"autogenerate": false,
"tags": []
},
"usage": {
"digital_products_count": 0,
"orders_count": 0
},
"digital_products": [],
"recent_orders": [],
"created_at": "2026-10-30T16:49:38Z",
"updated_at": "2026-10-30T16:49:38Z",
"upload": {
"url": "https://files.filemonk.io/uploads/5f3e9c1a/guide.pdf?X-Amz-Expires=3600&X-Amz-Signature=3f6c…",
"method": "PUT",
"headers": {
"Content-Type": "application/pdf"
},
"expires_at": "2026-10-31T00:10:00Z"
}
}{
"errors": [
"Invalid API key"
]
}{
"errors": [
"access.download_limit_count must be an integer of at least 0"
],
"field_errors": {
"access.download_limit_count": [
"must be an integer of at least 0"
]
}
}{
"errors": [
"You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
],
"code": "rate_limited",
"retry_after": 12,
"error": "Rate limit exceeded",
"message": "You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
}