API

yeah we got an api. cool right?

20req/min rate limit. no file size limit.

Endpoint

POST /api/upload

Small Files (<4MB)

send a multipart/form-data request with your file:

curl -F "file=@yourfile.png" https://cdn.eryxks.dev/api/upload

Big Files (>4MB)

two steps - get presigned url, then upload directly:

step 1: get upload url

curl -X POST https://cdn.eryxks.dev/api/upload \
  -H "Content-Type: application/json" \
  -d '{"filename": "bigfile.zip", "contentType": "application/zip"}'

step 2: upload to the uploadUrl (use headers from response!)

curl -X PUT "<uploadUrl from step 1>" \
  -H "Content-Type: application/zip" \
  -H "x-amz-acl: public-read" \
  --data-binary @bigfile.zip

Response

small files:

{
  "success": true,
  "url": "https://cdn.gcdn.space/aBc123xY.png",
  "filename": "aBc123xY.png",
  "originalName": "yourfile.png",
  "size": 12345,
  "type": "image/png"
}

big files (step 1 response):

{
  "success": true,
  "needsDirectUpload": true,
  "uploadUrl": "https://..presigned s3 url..",
  "uploadHeaders": {
    "Content-Type": "application/zip",
    "x-amz-acl": "public-read"
  },
  "url": "https://cdn.gcdn.space/xYz789aB.zip",
  "filename": "xYz789aB.zip",
  "originalName": "bigfile.zip"
}

Example (handles both)

async function upload(file) {
  if (file.size > 4 * 1024 * 1024) {
    const res = await fetch('https://cdn.eryxks.dev/api/upload', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ filename: file.name, contentType: file.type })
    });
    const data = await res.json();
    
    await fetch(data.uploadUrl, {
      method: 'PUT',
      headers: data.uploadHeaders,
      body: file
    });
    
    return data.url;
  } else {
    const form = new FormData();
    form.append('file', file);
    const res = await fetch('https://cdn.eryxks.dev/api/upload', { method: 'POST', body: form });
    const data = await res.json();
    return data.url;
  }
}

same rules as the web version. don't be stupid. tos applies

← back