Replace Asset File
Swap the file body of an existing internal asset in place, keeping the same asset ID and links.
Last updated
Use this to ship a new version of a file without re-wiring anything. The asset keeps its ID and stays attached to every digital product and order it was already linked to, so buyers downloading it receive the new file automatically — there is no need to create a fresh asset and re-attach it.
Only internal assets can be replaced. The flow mirrors
creating an internal asset: the response includes a single
presigned PUT URL — upload the new file body to that URL to finish. Once the
replacement is committed, the previous file is removed and any watermarking is
re-applied to the new body.
Plan storage quota is enforced on the growth in size (new byte_size minus
the current size); the per-file ceiling is 2 GB.
Path parameters
Section titled “Path parameters”-
id(string, path, required)The ID (UUID) of the internal asset to replace.
Request body
Section titled “Request body”-
asset(object, required)Asset fields:
-
filename(string, required)Suggested attachment name on download for the new file.
-
byte_size(integer, required)Size of the new file in bytes. Must be positive and at most 2 GB.
-
content_type(string)Optional MIME type for the new file. Defaults to the asset’s current content type, or
application/octet-stream.
-
Response
Section titled “Response”-
asset(object, required)The asset, with its ID unchanged.
-
upload(object, required)A single-PUT handle (
method: "PUT") with the presigned URL and headers required to upload the new file body. See Upload Asset for the field-by-field breakdown.
Example request
curl -X POST 'https://app.filemonk.io/api/v1/external/assets/a1b2c3d4-e5f6-7890-abcd-ef1234567890/replace' \ -H 'X-Auth-Token: fm_api_key_your_key_here' \ -H 'Content-Type: application/json' \ -d '{ "asset": { "filename": "brushes-pack-v3.zip", "byte_size": 2097152, "content_type": "application/zip" } }'const ASSET_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';const path = './brushes-pack-v3.zip';const { size } = await stat(path);
const replace = await fetch( `https://app.filemonk.io/api/v1/external/assets/${ASSET_ID}/replace`, { method: 'POST', headers: { 'X-Auth-Token': 'fm_api_key_your_key_here', 'Content-Type': 'application/json' }, body: JSON.stringify({ asset: { filename: 'brushes-pack-v3.zip', byte_size: size, content_type: 'application/zip' } }) }).then(r => r.json());
// Upload the new body to the presigned URL.await fetch(replace.upload.url, { method: 'PUT', headers: replace.upload.headers, body: await readFile(path)});ASSET_ID = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'path = './brushes-pack-v3.zip'
replace = requests.post( f'https://app.filemonk.io/api/v1/external/assets/{ASSET_ID}/replace', headers={'X-Auth-Token': 'fm_api_key_your_key_here'}, json={ 'asset': { 'filename': 'brushes-pack-v3.zip', 'byte_size': os.path.getsize(path), 'content_type': 'application/zip' } }).json()
with open(path, 'rb') as f: requests.put( replace['upload']['url'], headers=replace['upload']['headers'], data=f )Example response
{ "asset": { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "type": "internal", "name": "Photoshop Brushes Pack", "filename": "brushes-pack-v3.zip", "content_type": "application/zip", "byte_size": 2097152, "watermark_asset": false, "autogenerate_licence_key": false, "created_at": "2026-04-08T10:00:00Z", "updated_at": "2026-04-09T12:30:00Z" }, "upload": { "method": "PUT", "url": "https://<bucket>.r2.cloudflarestorage.com/external_api/<shop_id>/9c4b.zip?X-Amz-Signature=...", "headers": { "Content-Type": "application/zip", "Content-Disposition": "inline; filename=\"brushes-pack-v3.zip\"" }, "expires_at": "2026-04-09T13:30:00Z" }}{ "error": "Only internal assets can have their file replaced"}{ "error": "Asset not found"}Thanks for letting us know.
Still stuck? Ask Quinn or chat with support