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#
| Parameter | Type | Description |
|---|---|---|
organizationName | string | Required. Organization slug |
directoryId | string | Required. Directory ID to upload to |
Authentication#
Authenticate using API Key:
X-Snapkit-API-Key: sk_live_myorg_1234567890abcdefRequest Parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
files | File[] | Required | Image files to upload. Supported formats: JPEG, PNG, GIF, WebP, SVG, BMP, ICO, TIFF |
tags | string[] | Optional | Array of tags to add to images |
imageId | string | Optional | Custom 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#
| Field | Type | Description |
|---|---|---|
id | string | Unique asset ID |
filename | string | Filename |
url | string | CDN URL |
width | number | Image width (pixels) |
height | number | Image height (pixels) |
size | number | File size (bytes) |
format | string | Image format (jpeg, png, webp, etc.) |
directoryId | string | Parent directory ID |
directoryPath | string | Directory path |
tags | Tag[] | Array of tags |
createdAt | string | Creation time (ISO 8601) |
updatedAt | string | Last modified time (ISO 8601) |
Authentication#
Creating API Keys#
- Go to Settings > API Keys in the web dashboard
- Click Create API Key button
- Enter key name and set permissions
- 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-accessUsage:
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#
| Limit | Value |
|---|---|
| Max file size | 10MB |
| Max files per request | 100 files |
| Supported formats | JPEG, 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#
| Code | Description | Solution |
|---|---|---|
400 | Bad Request | Check request parameters |
401 | Unauthorized | Verify API Key |
403 | Forbidden | Check API Key permissions |
413 | Payload Too Large | Reduce file size to under 10MB |
429 | Too Many Requests | Wait for rate limit or adjust settings |
507 | Insufficient Storage | Upgrade 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-corprequire("dotenv").config();
const apiKey = process.env.SNAPKIT_API_KEY;Python:
# .env
SNAPKIT_API_KEY=sk_live_acme-corp_1234567890abcdefimport os
from dotenv import load_dotenv
load_dotenv()
api_key = os.getenv('SNAPKIT_API_KEY')Related Documentation#
- Image Transform API - Optimize uploaded images
- Next.js Integration - Use images in frontend
Support#
For any questions, please contact us:
- Chat: Chat button at bottom right
- Discord: https://discord.com/invite/RM6QgTW8↗
- GitHub: https://github.com/snapkit-studio/snapkit-js↗
- Email: support@snapkit.studio
