Media

File uploads, image management, and asset handling

The Media module handles file uploads, image processing, and asset management.

Upload Media

POST /v1/businesses/{businessId}/media
SDK: sdk.media.uploadBusinessMedia()

Upload files to your media library. Supports uploading multiple files and/or URLs.

// Upload from file input (multiple files)
const fileInput = document.querySelector('input[type="file"]');
const files = Array.from(fileInput.files);

const result = await sdk.media.uploadBusinessMedia({
files: files,  // Array of File objects
urls: [],      // Can also provide URLs to download
folder: 'products',
alt: 'Product images'
});

result.forEach(media => {
console.log('Uploaded:', media.url);
console.log('Media ID:', media.id);
});

// Upload from URLs
const urlResult = await sdk.media.uploadBusinessMedia({
files: [],
urls: [
  'https://example.com/image1.jpg',
  'https://example.com/image2.png'
],
folder: 'imports'
});

Parameters

Name Type Description
files optional File[] Array of files to upload
urls optional string[] Array of URLs to download and store
folder optional string Organization folder
alt optional string Alt text for accessibility
title optional string Media title
Note

At least one of files or urls must be provided with at least one item.

Supported File Types

CategoryExtensions
Images.jpg, .jpeg, .png, .gif, .webp, .svg, .avif
Documents.pdf, .doc, .docx, .xls, .xlsx
Video.mp4, .webm, .mov
Audio.mp3, .wav, .ogg

Size Limits

  • Images: 10MB
  • Documents: 25MB
  • Video: 100MB
  • Audio: 50MB

Get Media

GET /v1/businesses/{businessId}/media
SDK: sdk.media.getBusinessMedia()

List all media files.

const result = await sdk.media.getBusinessMedia({
mimeType: 'image/jpeg',
query: 'product hero',
limit: 50,
sortField: 'uploadedAt',
sortDirection: 'desc'
});

result.items.forEach(media => {
console.log(media.id, media.url, media.size);
});

Parameters

Name Type Description
ids optional string[] Filter by specific media IDs
mimeType optional string Filter by MIME type (image/jpeg, image/png, video/mp4, etc.)
query optional string Search in title and alt text
sortField optional string Sort field
sortDirection optional asc | desc Sort direction
cursor optional string Pagination cursor
limit required number Items per page

Update Media

PUT /v1/businesses/{businessId}/media/{mediaId}
SDK: sdk.media.updateMedia()

Update media metadata.

const result = await sdk.media.updateMedia({
  mediaId: 'media_xyz789',
  alt: 'Updated alt text',
  title: 'Product Photo - Front View',
  folder: 'products/featured'
});

Parameters

Name Type Description
mediaId required string Media ID to update
alt optional string Alt text
title optional string Media title
folder optional string Move to folder

Delete Media

DELETE /v1/businesses/{id}/media/{mediaId}
SDK: sdk.media.deleteBusinessMedia()

Delete a media file.

Warning

Deleting media that’s in use (products, nodes, etc.) may cause broken images. Check references before deleting.

const result = await sdk.media.deleteBusinessMedia({
  id: 'biz_abc123',
  mediaId: 'media_xyz789'
});

Parameters

Name Type Description
id required string Business ID
mediaId required string Media ID to delete

Image Transformations

Arky provides on-the-fly image transformations via URL parameters.

Resize

// Original URL
const originalUrl = media.url;
// https://cdn.arky.io/media/biz_abc123/image.jpg

// Resize to width 400px (height auto)
const resized = `${originalUrl}?w=400`;

// Resize to exact dimensions
const exact = `${originalUrl}?w=400&h=300`;

// Fit within bounds (maintain aspect ratio)
const fit = `${originalUrl}?w=400&h=300&fit=contain`;

// Cover (crop to fill)
const cover = `${originalUrl}?w=400&h=300&fit=cover`;

Quality

// Reduce quality for smaller file size
const compressed = `${originalUrl}?q=75`;

Format Conversion

// Convert to WebP
const webp = `${originalUrl}?format=webp`;

// Convert to AVIF
const avif = `${originalUrl}?format=avif`;

Transformation Parameters

ParameterDescriptionExample
wWidth in pixels?w=400
hHeight in pixels?h=300
fitResize modecontain, cover, fill
qQuality (1-100)?q=80
formatOutput formatwebp, avif, jpg, png
blurBlur amount (1-100)?blur=10
grayscaleConvert to grayscale?grayscale=true

Responsive Images

Generate srcset for responsive images:

function getResponsiveSrcSet(media: Media) {
  const baseUrl = media.url;
  const widths = [320, 640, 960, 1280, 1920];

  return widths
    .map(w => `${baseUrl}?w=${w}&format=webp ${w}w`)
    .join(', ');
}

// Usage in HTML
const srcSet = getResponsiveSrcSet(productImage);
// <img srcset={srcSet} sizes="(max-width: 768px) 100vw, 50vw" />

Upload with Progress

Track upload progress for large files:

async function uploadWithProgress(
  files: File[],
  onProgress: (percent: number) => void
) {
  const formData = new FormData();
  files.forEach((file, i) => {
    formData.append(`files[${i}]`, file);
  });

  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable) {
        const percent = Math.round((e.loaded / e.total) * 100);
        onProgress(percent);
      }
    });

    xhr.addEventListener('load', () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(JSON.parse(xhr.responseText));
      } else {
        reject(new Error('Upload failed'));
      }
    });

    xhr.open('POST', `https://api.arky.io/v1/businesses/${businessId}/media`);
    xhr.setRequestHeader('Authorization', `Bearer ${token}`);
    xhr.send(formData);
  });
}

// Usage
await uploadWithProgress(files, (percent) => {
  console.log(`Upload progress: ${percent}%`);
  progressBar.style.width = `${percent}%`;
});

Bulk Upload

Upload multiple files using the SDK:

async function uploadMultiple(files: File[]) {
  // The SDK handles batching automatically
  const results = await sdk.media.uploadBusinessMedia({
    files: files,
    folder: 'bulk-import'
  });

  console.log(`Uploaded ${results.length} files`);
  return results;
}

// Usage
const fileInput = document.querySelector('input[type="file"][multiple]');
const uploaded = await uploadMultiple([...fileInput.files]);

Media in Products/Nodes

Reference media by ID when creating products or content:

// Upload images first
const uploadResult = await sdk.media.uploadBusinessMedia({
  files: [heroFile, ...galleryFiles],
  folder: 'products'
});

const [heroMedia, ...galleryMedia] = uploadResult;

// Create product with media references
await sdk.eshop.createProduct({
  key: 'my-product',
  blocks: [
    {
      key: 'hero-image',
      type: 'IMAGE',
      content: {
        mediaId: heroMedia.id
      }
    },
    {
      key: 'gallery',
      type: 'GALLERY',
      content: {
        mediaIds: galleryMedia.map(m => m.id)
      }
    }
  ],
  status: 'ACTIVE'
});
Tip

Use folders to organize media by type (products, blog, team, etc.) for easier management.