Assets Block

Enterprise Digital Asset Management for modern applications
The Assets Block is a complete Digital Asset Management (DAM) solution that provides centralized media storage, on-the-fly image transformations, global CDN delivery, rich metadata management, and version control. Build powerful media libraries for e-commerce, content publishing, and brand management.
Key Features
- Media Library - Centralized storage for images, videos, documents, and any file type
- Asset Transformations - On-the-fly resizing, cropping, format conversion, and optimization
- CDN Delivery - Global content delivery network for fast asset serving worldwide
- Metadata Management - Rich metadata with custom fields, tags, and categories
- Version Control - Track asset versions, revisions, and maintain audit history
- Access Control - Fine-grained permissions with expiring links and watermarking
- Smart Search - Full-text search across filenames, metadata, and tags
- Folder Organization - Hierarchical folder structure with virtual collections
Base URLs
| Environment | URL |
|---|---|
| Production | https://assets.23blocks.com |
| Staging | https://staging-assets.23blocks.com |
| Development | https://dev-assets.23blocks.com |
Quick Start
Installation
npm install @23blocks/sdk
Basic Usage
import { BlocksClient } from '@23blocks/sdk';
const client = new BlocksClient({
baseUrl: 'https://assets.23blocks.com',
apiKey: 'your-api-key'
});
// Upload an asset
const asset = await client.assets.upload({
file: fileBlob,
folder: 'products/images',
metadata: {
title: 'Product Hero Image',
tags: ['product', 'hero', 'featured'],
alt: 'Product front view'
}
});
// Get transformed URL
const thumbnailUrl = client.assets.getUrl(asset.id, {
width: 400,
height: 400,
format: 'webp',
quality: 85
});
// Search assets
const results = await client.assets.search({
query: 'product hero',
folder: 'products',
tags: ['featured']
});
Authentication
Required Headers
All API requests require authentication:
Authorization: Bearer [JWT_TOKEN]
X-API-Key: [COMPANY_API_KEY]
Content-Type: application/json
For asset uploads, use multipart/form-data:
Content-Type: multipart/form-data
API Reference
Upload Asset
Upload a new asset to the media library.
curl -X POST https://assets.23blocks.com/assets \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-F "file=@/path/to/image.jpg" \
-F "folder=products/images" \
-F "metadata[title]=Product Hero" \
-F "metadata[tags][]=product" \
-F "metadata[tags][]=featured" \
-F "metadata[alt]=Product front view"
Response:
{
"data": {
"id": "asset_abc123",
"type": "asset",
"attributes": {
"unique_id": "asset_abc123",
"filename": "product-hero.jpg",
"original_filename": "image.jpg",
"content_type": "image/jpeg",
"size": 1245678,
"folder": "products/images",
"url": "https://cdn.23blocks.com/assets/products/images/product-hero.jpg",
"metadata": {
"title": "Product Hero",
"tags": ["product", "featured"],
"alt": "Product front view"
},
"dimensions": {
"width": 2400,
"height": 1600
},
"version": 1,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
}
Get Asset
Retrieve asset metadata by ID.
curl -X GET https://assets.23blocks.com/assets/asset_abc123 \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"
Update Asset Metadata
Update metadata for an existing asset.
curl -X PATCH https://assets.23blocks.com/assets/asset_abc123 \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "asset",
"attributes": {
"metadata": {
"title": "Updated Product Hero",
"tags": ["product", "featured", "sale"]
}
}
}
}'
Upload New Version
Upload a new version of an existing asset.
curl -X POST https://assets.23blocks.com/assets/asset_abc123/versions \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-F "file=@/path/to/updated-image.jpg" \
-F "comment=Updated product photography"
Response:
{
"data": {
"id": "asset_abc123",
"type": "asset",
"attributes": {
"version": 2,
"versions": [
{
"version": 1,
"url": "https://cdn.23blocks.com/assets/.../v1/product-hero.jpg",
"created_at": "2024-01-15T10:30:00Z"
},
{
"version": 2,
"url": "https://cdn.23blocks.com/assets/.../v2/product-hero.jpg",
"comment": "Updated product photography",
"created_at": "2024-01-16T14:20:00Z"
}
]
}
}
}
List Version History
Get all versions of an asset.
curl -X GET https://assets.23blocks.com/assets/asset_abc123/versions \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"
Rollback to Version
Restore a previous version as the current version.
curl -X POST https://assets.23blocks.com/assets/asset_abc123/rollback \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"version": 1
}'
List Assets
List assets with filtering and pagination.
curl -X GET "https://assets.23blocks.com/assets?folder=products&tags=featured&page=1&per_page=20" \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
folder | string | Filter by folder path |
tags | string | Filter by tags (comma-separated) |
content_type | string | Filter by MIME type (e.g., image/*) |
search | string | Full-text search query |
created_after | datetime | Filter by creation date |
created_before | datetime | Filter by creation date |
sort | string | Sort field (created_at, updated_at, filename) |
order | string | Sort order (asc or desc) |
page | integer | Page number (default: 1) |
per_page | integer | Items per page (default: 20, max: 100) |
Search Assets
Search across all assets using full-text search.
curl -X POST https://assets.23blocks.com/assets/search \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"query": "product hero",
"filters": {
"folder": "products",
"tags": ["featured"],
"content_type": "image/*"
},
"facets": ["tags", "folder", "content_type"]
}'
Response:
{
"data": [...],
"meta": {
"total": 45,
"facets": {
"tags": [
{"value": "product", "count": 30},
{"value": "featured", "count": 15}
],
"folder": [
{"value": "products/images", "count": 25},
{"value": "products/videos", "count": 20}
]
}
}
}
Delete Asset
Delete an asset and all its versions.
curl -X DELETE https://assets.23blocks.com/assets/asset_abc123 \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"
Image Transformations
Transform images on-the-fly by appending parameters to the asset URL.
URL Format
https://cdn.23blocks.com/assets/{path}?w={width}&h={height}&f={format}&q={quality}
Transformation Parameters
| Parameter | Description | Example |
|---|---|---|
w | Width in pixels | w=400 |
h | Height in pixels | h=300 |
f | Output format (jpg, png, webp, avif) | f=webp |
q | Quality (1-100) | q=85 |
fit | Resize mode (cover, contain, fill, inside, outside) | fit=cover |
crop | Crop position (center, top, bottom, left, right) | crop=center |
blur | Blur amount (1-100) | blur=10 |
sharpen | Sharpen amount (1-100) | sharpen=20 |
grayscale | Convert to grayscale | grayscale=true |
rotate | Rotation angle (0, 90, 180, 270) | rotate=90 |
Examples
Thumbnail (200x200, WebP):
https://cdn.23blocks.com/assets/products/hero.jpg?w=200&h=200&fit=cover&f=webp
Responsive Hero Image:
https://cdn.23blocks.com/assets/products/hero.jpg?w=1200&h=600&fit=cover&q=85
Grayscale with Blur:
https://cdn.23blocks.com/assets/products/hero.jpg?grayscale=true&blur=5
SDK Usage
// Generate transformed URL
const thumbnailUrl = client.assets.transform(asset.id, {
width: 400,
height: 400,
fit: 'cover',
format: 'webp',
quality: 85
});
// Generate multiple sizes (responsive images)
const responsive = client.assets.responsive(asset.id, {
sizes: [400, 800, 1200, 1600],
format: 'webp'
});
// Returns: { 400: url, 800: url, 1200: url, 1600: url }
Folder Management
Create Folder
curl -X POST https://assets.23blocks.com/folders \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "folder",
"attributes": {
"name": "Product Photos",
"path": "products/photos",
"metadata": {
"description": "High-resolution product photography"
}
}
}
}'
List Folders
curl -X GET "https://assets.23blocks.com/folders?parent=products" \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"
Move Assets to Folder
curl -X POST https://assets.23blocks.com/assets/move \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"asset_ids": ["asset_abc123", "asset_def456"],
"destination_folder": "products/archive"
}'
Access Control
Generate Secure Share Link
Create a time-limited shareable link with optional watermarking.
curl -X POST https://assets.23blocks.com/assets/asset_abc123/share \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"expires_in": 86400,
"watermark": {
"text": "Preview Only",
"position": "bottom-right",
"opacity": 0.5
},
"max_downloads": 10,
"password": "optional-password"
}'
Response:
{
"data": {
"share_url": "https://cdn.23blocks.com/share/xyz789...",
"expires_at": "2024-01-16T10:30:00Z",
"downloads_remaining": 10
}
}
Set Asset Permissions
curl -X PATCH https://assets.23blocks.com/assets/asset_abc123/permissions \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"public": false,
"allowed_users": ["user_123", "user_456"],
"allowed_roles": ["editor", "admin"]
}'
Collections
Create virtual collections to organize assets across folders.
Create Collection
curl -X POST https://assets.23blocks.com/collections \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"data": {
"type": "collection",
"attributes": {
"name": "2024 Spring Campaign",
"description": "Assets for spring marketing campaign",
"asset_ids": ["asset_abc123", "asset_def456"]
}
}
}'
Add Assets to Collection
curl -X POST https://assets.23blocks.com/collections/coll_xyz/assets \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"asset_ids": ["asset_ghi789"]
}'
Webhooks
Subscribe to asset events for real-time notifications.
Available Events
| Event | Description |
|---|---|
asset.created | New asset uploaded |
asset.updated | Asset metadata updated |
asset.deleted | Asset deleted |
asset.version.created | New version uploaded |
asset.transformed | Transformation generated |
asset.shared | Share link created |
collection.created | Collection created |
collection.updated | Collection modified |
Webhook Payload
{
"event": "asset.created",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"id": "asset_abc123",
"type": "asset",
"attributes": {
"filename": "product-hero.jpg",
"folder": "products/images",
"url": "https://cdn.23blocks.com/assets/..."
}
}
}
SDK Reference
TypeScript/JavaScript
import { BlocksClient } from '@23blocks/sdk';
const client = new BlocksClient({
baseUrl: 'https://assets.23blocks.com',
apiKey: 'your-api-key'
});
// Upload with progress tracking
const asset = await client.assets.upload({
file: fileBlob,
folder: 'products',
metadata: { title: 'Product Photo' },
onProgress: (progress) => {
console.log(`${progress.percent}% uploaded`);
}
});
// Batch operations
const results = await client.assets.batch({
operations: [
{ action: 'move', asset_id: 'asset_1', folder: 'archive' },
{ action: 'tag', asset_id: 'asset_2', tags: ['featured'] },
{ action: 'delete', asset_id: 'asset_3' }
]
});
React Hook
import { useAssets } from '@23blocks/react';
function MediaLibrary() {
const { assets, loading, upload, search } = useAssets({
folder: 'products'
});
const handleUpload = async (files: FileList) => {
for (const file of files) {
await upload(file, {
folder: 'products',
metadata: { title: file.name }
});
}
};
return (
<div>
<input type="file" multiple onChange={(e) => handleUpload(e.target.files)} />
<input
type="search"
placeholder="Search assets..."
onChange={(e) => search(e.target.value)}
/>
{assets.map(asset => (
<img key={asset.id} src={asset.thumbnailUrl} alt={asset.metadata.title} />
))}
</div>
);
}
Error Handling
| Status Code | Error Type | Description |
|---|---|---|
| 400 | validation_error | Invalid request parameters |
| 401 | authentication_error | Invalid or missing credentials |
| 403 | authorization_error | Insufficient permissions |
| 404 | not_found | Asset or folder not found |
| 409 | conflict | Asset already exists |
| 413 | payload_too_large | File exceeds size limit |
| 415 | unsupported_media_type | File type not allowed |
| 429 | rate_limit_exceeded | Too many requests |
| 500 | internal_error | Server error |
Rate Limits
| Plan | Uploads/min | Transformations/min | API Calls/min |
|---|---|---|---|
| Free | 10 | 100 | 1,000 |
| Pro | 100 | 1,000 | 10,000 |
| Enterprise | Unlimited | Unlimited | Custom |
Related Resources
- Marketing Page - Feature overview
- API Reference - Interactive API documentation
- Platform Status - Service uptime monitoring