IzFiles

Developer API

IzFiles API Guide

Upload files, share and embed them, and manage them from your own code or website. Every endpoint answers with JSON.

Base URLhttps://izfiles.com
AuthX-API-KEY header
FormatJSON responses
Log in to see your API key. No key yet? Contact the administrator to request API access.

Authentication

Every API call needs your API key. Send it in a header:

X-API-KEY: YOUR_API_KEY
  • Authorization: Bearer YOUR_API_KEY works too.
  • Upload and note calls also accept the key as a token form field.
  • A key in the query string (?token=...) is refused with 400, so it never ends up in logs.
  • Files are saved to the account the key belongs to, and count toward its storage limit.
Each account has its own key. If you do not have one, ask the administrator.

Quick start

Upload a file and read the link from the answer:

curl -H "X-API-KEY: YOUR_API_KEY" \
     -F "file=@/path/to/report.pdf" \
     https://izfiles.com/api/upload
{
  "success": true,
  "file_hash": "abc123def456",
  "filename": "report.pdf",
  "privacy": "private",
  "share_url": "https://izfiles.com/share/abc123def456",
  "download_url": "https://izfiles.com/download/abc123def456",
  "access": "link"
}

Keep the file_hash: every other call uses it.

Limits and quotas

WhatLimit
One upload requestAbout 95 MB. Cloudflare answers 413 above 100 MB; use chunked upload for bigger files.
File sizeSet by your account group (for example 10 GB per file), and the file counts toward your storage.
/api/upload and chunked start1000 per hour per IP address
Chunk, status, cancel and complete calls300 per minute and 20000 per hour per IP address
File info and list300 per hour per IP address
Signed links2000 per hour per IP address
Delete1000 per hour per IP address
Notes60 per hour per IP address
/direct links500 per minute per viewer IP address
DownloadsDaily request and bandwidth quotas per viewer IP address

The administrator can change these limits. A call over a limit answers 429; responses carry X-RateLimit-* headers.

Upload a file

POST/api/uploadmultipart/form-data
FieldRequiredDescription
fileYesThe file to upload.
privacyNoprivate (default): not listed on Explore, anyone with the link can open it. public: listed on Explore.
accessNolink (default) or signed. signed needs privacy=private; see signed links.
expires_inNonever (default), 1d, 7d or 30d. After that time the file can no longer be opened.
tokenNoYour API key, if you do not send the X-API-KEY header.
curl -H "X-API-KEY: YOUR_API_KEY" \
     -F "file=@/path/to/photo.png" \
     -F "privacy=public" \
     https://izfiles.com/api/upload
import requests

with open("photo.png", "rb") as handle:
    response = requests.post(
        "https://izfiles.com/api/upload",
        headers={"X-API-KEY": "YOUR_API_KEY"},
        files={"file": handle},
        data={"privacy": "public"},
    )
result = response.json()
print(result["share_url"])
if result.get("direct_url"):
    print("Embed:", result["direct_url"])
const fs = require('fs');

async function uploadFile(path) {
  const form = new FormData(); // Node.js 18 or later
  form.append('file', new Blob([fs.readFileSync(path)]), require('path').basename(path));
  const response = await fetch('https://izfiles.com/api/upload', {
    method: 'POST',
    headers: { 'X-API-KEY': process.env.IZFILES_API_KEY },
    body: form,
  });
  return response.json(); // file_hash, share_url, download_url ...
}
The answer includes direct_url for public images and videos. Private ones can be embedded too: build the link yourself as https://izfiles.com/direct/<file_hash>. See direct links.

Upload from a URL

The server downloads the file for you. Same endpoint, with url instead of file.

POST/api/uploadmultipart/form-data
FieldRequiredDescription
urlYesPublic http or https link to the file. Private network addresses are refused.
privacy, access, expires_inNoAs in Upload a file.
curl -H "X-API-KEY: YOUR_API_KEY" \
     -F "url=https://example.com/file.pdf" \
     https://izfiles.com/api/upload

The download must finish within 5 minutes and stay under your file size limit. The answer also has source_url.

Large files in chunks

For files over about 95 MB: start an upload, send the file in pieces, then complete it. The result is the same as /api/upload, and the same size and storage limits apply.

  1. Start

    POST/api/upload/chunked/startform or JSON
    FieldRequiredDescription
    filenameYesName of the file.
    file_sizeYesSize in bytes.
    chunk_sizeNoBytes per chunk, 1 MB to 90 MB. Default 50 MB (52428800).
    privacy, access, expires_inNoAs in Upload a file.
    {
      "success": true,
      "upload_id": "3f2a9c...",
      "chunk_size": 52428800,
      "total_chunks": 12,
      "received_chunks": 0,
      "missing_chunks": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
      "expires_at": "2026-11-13T10:00:00Z"
    }
  2. Send every chunk

    PUT/api/upload/chunked/<upload_id>/<index>multipart, field file

    Indexes run from 0 to total_chunks - 1. Every chunk is exactly chunk_size bytes, except the last one, which is the rest of the file.

    Send each chunk as multipart/form-data in the field file. A raw application/octet-stream body is blocked by the web application firewall.
  3. Complete

    POST/api/upload/chunked/<upload_id>/completeoptional md5

    Send the md5 of the whole file to have it checked. The answer has the same fields as /api/upload, plus upload_id and md5.

# 1. Start
curl -X POST -H "X-API-KEY: YOUR_API_KEY" \
     -F "filename=big.zip" -F "file_size=629145600" \
     https://izfiles.com/api/upload/chunked/start

# 2. Split into 50 MB parts and send each one (index 0, 1, 2 ...)
split -b 52428800 -d -a 4 big.zip part_
curl -X PUT -H "X-API-KEY: YOUR_API_KEY" -F "file=@part_0000" \
     https://izfiles.com/api/upload/chunked/UPLOAD_ID/0

# 3. Complete
curl -X POST -H "X-API-KEY: YOUR_API_KEY" -F "md5=$(md5sum big.zip | cut -d' ' -f1)" \
     https://izfiles.com/api/upload/chunked/UPLOAD_ID/complete
const fs = require('fs');
const path = require('path');
const axios = require('axios');

async function uploadLarge(filePath, options = {}) {
  const api = axios.create({
    baseURL: 'https://izfiles.com/api/upload/chunked',
    headers: { 'X-API-KEY': process.env.IZFILES_API_KEY },
    maxBodyLength: Infinity,
  });
  const fileSize = fs.statSync(filePath).size;
  const { data: start } = await api.post('/start', {
    filename: path.basename(filePath), file_size: fileSize, ...options,
  });
  const handle = await fs.promises.open(filePath, 'r');
  try {
    for (let index = 0; index < start.total_chunks; index++) {
      const length = Math.min(start.chunk_size, fileSize - index * start.chunk_size);
      const chunk = Buffer.alloc(length);
      await handle.read(chunk, 0, length, index * start.chunk_size);
      for (let attempt = 1; ; attempt++) {
        try {
          const form = new FormData(); // Node.js 18 or later
          form.append('file', new Blob([chunk]), `part_${index}`);
          await api.put(`/${start.upload_id}/${index}`, form);
          break;
        } catch (err) {
          if (attempt === 3 || err.response?.status === 400) throw err;
        }
      }
    }
  } finally {
    await handle.close();
  }
  const { data } = await api.post(`/${start.upload_id}/complete`);
  return data; // same fields as /api/upload
}

Good to know

  • Chunks can be sent in any order and in parallel. Sending a chunk again replaces it, so retry a failed chunk as it is.
  • GET /api/upload/chunked/<upload_id> lists missing_chunks, so an interrupted upload can resume. After completion it returns the result.
  • Calling complete again returns the same file, not a second copy. If complete answers 400 with missing_chunks, send those and complete again.
  • DELETE /api/upload/chunked/<upload_id> cancels an unfinished upload. Uploads are removed 24 hours after start.
  • An account can have up to 50 unfinished uploads at once.

Get file info

GET/api/file/<file_hash>
curl -H "X-API-KEY: YOUR_API_KEY" https://izfiles.com/api/file/abc123def456
{
  "success": true,
  "file_hash": "abc123def456",
  "filename": "example.png",
  "privacy": "public",
  "access": "link",
  "file_size": 1024000,
  "file_type": "png",
  "is_image": true,
  "upload_date": "2026-11-12T10:30:00",
  "download_count": 5,
  "has_password": false,
  "share_url": "https://izfiles.com/share/abc123def456",
  "direct_url": "https://izfiles.com/direct/abc123def456"
}

For a signed file, only its owner or an admin gets an answer, and the plain links are left out.

List files

GET/api/files
QueryDefaultDescription
page1Page number.
per_page20Items per page, at most 100.
privacyallall, public or private.
typeallall or image.
curl -H "X-API-KEY: YOUR_API_KEY" \
     "https://izfiles.com/api/files?privacy=public&type=image&per_page=10"
{
  "success": true,
  "files": [
    { "file_hash": "abc123def456", "filename": "example.png", "privacy": "public", "access": "link", "...": "..." }
  ],
  "pagination": { "page": 1, "per_page": 10, "total": 50, "pages": 5, "has_next": true, "has_prev": false }
}

Delete a file

DELETE/api/file/<file_hash>
curl -X DELETE -H "X-API-KEY: YOUR_API_KEY" https://izfiles.com/api/file/abc123def456
async function deleteIzfile(fileHash) {
  try {
    await axios.delete(`https://izfiles.com/api/file/${fileHash}`, {
      headers: { 'X-API-KEY': process.env.IZFILES_API_KEY },
    });
  } catch (err) {
    // 404: already deleted, or not a file of this API key.
    if (err.response?.status !== 404) throw err;
  }
}
{ "success": true, "file_hash": "abc123def456", "deleted": true }
  • Only the owner or an admin can delete a file. It cannot be undone, and every link stops working at once, signed links included.
  • 404: the file does not exist or is not yours. When retrying a delete, treat it as already deleted.
  • 503 with Retry-After: the server is busy and nothing was deleted. Retry later.

Create a note

POST/api/notesmultipart/form-data
FieldRequiredDescription
titleYesNote title.
bodyOne of the twoNote text.
fileOne of the twoA UTF-8 text file to use as the note text.
typeNocontent (default) or code.
privacyNoprivate (default) or public.
curl -H "X-API-KEY: YOUR_API_KEY" \
     -F "title=Release notes" \
     -F "body=Version 2 is out." \
     https://izfiles.com/api/notes

# Code note from a file
curl -H "X-API-KEY: YOUR_API_KEY" \
     -F "title=Deploy script" -F "type=code" \
     -F "file=@/path/to/deploy.sh" \
     https://izfiles.com/api/notes
{
  "success": true,
  "note_id": 123,
  "title": "Release notes",
  "type": "content",
  "privacy": "private",
  "created_at": "2026-11-12T10:30:00",
  "share_url": "https://izfiles.com/view_shared_note/abc123..."
}

Responses

A successful call answers with "success": true. Upload answers carry these fields:

FieldDescription
file_hashThe file's ID in every other call and link.
filename, file_size, file_typeName, size in bytes and extension.
privacy, accessAs sent at upload.
is_imagetrue for images.
share_url, download_urlPlain links. Left out for signed files.
direct_urlOnly for public images and videos without a password.
upload_dateUTC time, ISO 8601.

A failed call answers with an HTTP error status and an error message:

{ "error": "Invalid token" }

Errors

StatusMeaningWhat to do
400A field is missing or not valid, a chunk has the wrong size, or the key was sent in the query string.Read error and fix the request.
401Missing token or Invalid token.Check the API key.
403Password needed, file type not allowed on /direct, or a signed link problem: signature_required, invalid_signature, link_expired.Send X-File-Password, or request a new signed link.
404The file or upload does not exist, or is not yours.Check the file_hash.
409A chunked upload is being completed.Wait a few seconds and call complete again.
413The request is over 100 MB.Use chunked upload.
429A rate limit or download quota was reached.Slow down and retry later.
503The server is busy ("retryable": true).Retry after the seconds in Retry-After.
507The server is low on space.Retry later.

Direct link formats

Any file type that is not blocked can be uploaded and downloaded. /direct serves these:

Images

JPG, JPEG, PNG, GIF, BMP, WebP, TIFF, ICO, HEIC

Videos

MP4, M4V, WebM, MOV, OGV

Script and web page files (for example PHP, JS, HTML, SVG, EXE) cannot be uploaded.

Troubleshooting

413 when uploading a big file

One request can carry about 95 MB. Use chunked upload.

A chunk answers 400 "blocked by the web application firewall"

The chunk was sent as a raw body. Send it as multipart/form-data in the field file.

401 on every call

The key is missing or wrong. Send it in the X-API-KEY header, not in the URL.

An embedded image does not show on my website

Check that the file is an image or video, has no password, and, if it is signed, that the link has not expired. Use /direct/<file_hash>, not /share.

fetch() of a private image fails with a CORS error

Only public files allow fetch() from other sites. Private files can still be shown with <img> and <video>, or fetched from your server.

429 Too Many Requests

A rate limit or download quota was reached. See limits, slow down and retry later.

Still stuck? Write to [email protected].