Upload API#

Upload images programmatically using Snapkit's Upload API.

Overview#

The Upload API uploads images to Snapkit via HTTP POST requests. Authenticated requests use API Keys to store images in your organization's storage.

Key Features:

  • Multipart/form-data format support
  • Upload up to 100 files at once
  • Automatic image metadata extraction
  • Tag and classification support

Upload#

Upload images.

HTTP Request#

POST https://api.snapkit.studio/organization/{organizationName}/images/{directoryId}

URL Parameters#

ParameterTypeDescription
organizationNamestring

Required. Organization slug

directoryIdstring

Required. Directory ID to upload to

Authentication#

Authenticate using API Key:

X-Snapkit-API-Key: sk_live_myorg_1234567890abcdef

Request Parameters#

ParameterTypeRequiredDescription
filesFile[]RequiredImage files to upload. Supported formats: JPEG, PNG, GIF, WebP, SVG, BMP, ICO, TIFF
tagsstring[]OptionalArray of tags to add to images
imageIdstringOptionalCustom filename. Uses original filename if not provided

Request Examples#

cURL:

curl -X POST "https://api.snapkit.studio/organization/acme-corp/images/dir-uuid" \
  -H "X-Snapkit-API-Key: sk_live_acme-corp_1234567890abcdef" \
  -F "files=@hero.jpg" \
  -F "files=@banner.png" \
  -F "tags=landing" \
  -F "tags=hero"

JavaScript (Fetch):

const formData = new FormData();
formData.append("files", file1);
formData.append("files", file2);
formData.append("tags", "landing");
formData.append("tags", "hero");
 
const response = await fetch("https://api.snapkit.studio/organization/acme-corp/images/dir-uuid", {
  method: "POST",
  headers: {
    "X-Snapkit-API-Key": "sk_live_acme-corp_1234567890abcdef",
  },
  body: formData,
});
 
const assets = await response.json();

Python:

import requests
 
url = 'https://api.snapkit.studio/organization/acme-corp/images/dir-uuid'
headers = {'X-Snapkit-API-Key': 'sk_live_acme-corp_1234567890abcdef'}
files = [
    ('files', open('hero.jpg', 'rb')),
    ('files', open('banner.png', 'rb'))
]
data = {'tags': ['landing', 'hero']}
 
response = requests.post(url, headers=headers, files=files, data=data)
assets = response.json()

Response#

Success (201 Created):

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "filename": "hero.jpg",
    "url": "https://acme-corp-cdn.snapkit.studio/project/hero.jpg",
    "width": 1920,
    "height": 1080,
    "size": 245678,
    "format": "jpeg",
    "directoryId": "dir-uuid",
    "directoryPath": "/images/landing",
    "tags": [
      {
        "id": "tag-uuid-1",
        "name": "landing"
      },
      {
        "id": "tag-uuid-2",
        "name": "hero"
      }
    ],
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
]

Response Fields#

FieldTypeDescription
idstringUnique asset ID
filenamestringFilename
urlstringCDN URL
widthnumberImage width (pixels)
heightnumberImage height (pixels)
sizenumberFile size (bytes)
formatstringImage format (jpeg, png, webp, etc.)
directoryIdstringParent directory ID
directoryPathstringDirectory path
tagsTag[]Array of tags
createdAtstringCreation time (ISO 8601)
updatedAtstringLast modified time (ISO 8601)

Authentication#

Creating API Keys#

  1. Go to Settings > API Keys in the web dashboard
  2. Click Create API Key button
  3. Enter key name and set permissions
  4. The generated key is shown only once, save it immediately in a secure location

Key Format:

  • Test: sk_test_{organizationName}_{randomString}
  • Production: sk_live_{organizationName}_{randomString}

SDK Examples#

JavaScript/TypeScript#

Installation:

npm install @repo/data-access

Usage:

import { useImageControllerUploadImages } from '@repo/data-access/web';
 
function UploadComponent() {
  const uploadMutation = useImageControllerUploadImages();
 
  async function handleUpload(files: File[]) {
    const assets = await uploadMutation.mutateAsync({
      organizationName: 'acme-corp',
      directoryId: 'dir-uuid',
      data: {
        files,
        tags: ['landing', 'hero']
      }
    });
 
    console.log('Uploaded:', assets);
  }
 
  return (
    <input
      type="file"
      multiple
      onChange={(e) => handleUpload(Array.from(e.target.files || []))}
    />
  );
}

Node.js#

const FormData = require("form-data");
const fs = require("fs");
const axios = require("axios");
 
async function uploadImages(filePaths, directoryId, apiKey) {
  const formData = new FormData();
 
  filePaths.forEach((filePath) => {
    formData.append("files", fs.createReadStream(filePath));
  });
 
  formData.append("tags", "landing");
 
  const response = await axios.post(`https://api.snapkit.studio/organization/acme-corp/images/${directoryId}`, formData, {
    headers: {
      "X-Snapkit-API-Key": apiKey,
      ...formData.getHeaders(),
    },
  });
 
  return response.data;
}

Python#

import requests
 
def upload_images(files, directory_id, api_key):
    url = f'https://api.snapkit.studio/organization/acme-corp/images/{directory_id}'
    headers = {'X-Snapkit-API-Key': api_key}
 
    files_data = [('files', open(f, 'rb')) for f in files]
    data = {'tags': ['landing', 'hero']}
 
    response = requests.post(url, headers=headers, files=files_data, data=data)
    return response.json()

Limitations#

File Limits#

LimitValue
Max file size10MB
Max files per request100 files
Supported formatsJPEG, PNG, GIF, WebP, SVG, BMP, ICO, TIFF

Rate Limiting#

API Key:

  • No default limit
  • Custom rate limits can be set per key

Error Handling#

Error Response Format#

{
  "statusCode": 401,
  "message": "Unauthorized access",
  "error": "Unauthorized"
}

Error Codes#

CodeDescriptionSolution
400Bad RequestCheck request parameters
401UnauthorizedVerify API Key
403ForbiddenCheck API Key permissions
413Payload Too LargeReduce file size to under 10MB
429Too Many RequestsWait for rate limit or adjust settings
507Insufficient StorageUpgrade plan or delete existing images

Error Handling Example#

try {
  const response = await fetch(uploadUrl, {
    method: "POST",
    headers: { "X-Snapkit-API-Key": apiKey },
    body: formData,
  });
 
  if (!response.ok) {
    const error = await response.json();
 
    switch (response.status) {
      case 401:
        console.error("Authentication failed:", error.message);
        // Re-login or refresh API Key
        break;
      case 413:
        console.error("File size exceeded:", error.message);
        // Compress file or split upload
        break;
      case 507:
        console.error("Storage capacity exceeded:", error.message);
        // Show plan upgrade notice
        break;
      default:
        console.error("Upload failed:", error.message);
    }
 
    throw new Error(error.message);
  }
 
  return await response.json();
} catch (error) {
  console.error("Error during upload:", error);
  throw error;
}

Security#

API Key Security#

Best Practices:

  • Store API Key in environment variables
  • Add environment variable file to .gitignore
  • Separate production/development environment keys
  • Rotate keys regularly
  • Apply principle of least privilege

Prohibited Actions:

  • Do not commit keys to Git repository
  • Do not expose keys in client code
  • Do not share keys in public channels

HTTPS Required#

All API requests must be sent over HTTPS:

// Correct usage
const url = "https://api.snapkit.studio/...";
 
// Security risk (do not use)
const url = "http://api.snapkit.studio/...";

Environment Variable Setup#

Node.js:

# .env
SNAPKIT_API_KEY=sk_live_acme-corp_1234567890abcdef
SNAPKIT_ORG_NAME=acme-corp
require("dotenv").config();
const apiKey = process.env.SNAPKIT_API_KEY;

Python:

# .env
SNAPKIT_API_KEY=sk_live_acme-corp_1234567890abcdef
import os
from dotenv import load_dotenv
 
load_dotenv()
api_key = os.getenv('SNAPKIT_API_KEY')

Support#

For any questions, please contact us: