Skip to main content

Assets Block

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

EnvironmentURL
Productionhttps://assets.23blocks.com
Staginghttps://staging-assets.23blocks.com
Developmenthttps://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:

ParameterTypeDescription
folderstringFilter by folder path
tagsstringFilter by tags (comma-separated)
content_typestringFilter by MIME type (e.g., image/*)
searchstringFull-text search query
created_afterdatetimeFilter by creation date
created_beforedatetimeFilter by creation date
sortstringSort field (created_at, updated_at, filename)
orderstringSort order (asc or desc)
pageintegerPage number (default: 1)
per_pageintegerItems 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

ParameterDescriptionExample
wWidth in pixelsw=400
hHeight in pixelsh=300
fOutput format (jpg, png, webp, avif)f=webp
qQuality (1-100)q=85
fitResize mode (cover, contain, fill, inside, outside)fit=cover
cropCrop position (center, top, bottom, left, right)crop=center
blurBlur amount (1-100)blur=10
sharpenSharpen amount (1-100)sharpen=20
grayscaleConvert to grayscalegrayscale=true
rotateRotation 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

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

EventDescription
asset.createdNew asset uploaded
asset.updatedAsset metadata updated
asset.deletedAsset deleted
asset.version.createdNew version uploaded
asset.transformedTransformation generated
asset.sharedShare link created
collection.createdCollection created
collection.updatedCollection 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 CodeError TypeDescription
400validation_errorInvalid request parameters
401authentication_errorInvalid or missing credentials
403authorization_errorInsufficient permissions
404not_foundAsset or folder not found
409conflictAsset already exists
413payload_too_largeFile exceeds size limit
415unsupported_media_typeFile type not allowed
429rate_limit_exceededToo many requests
500internal_errorServer error

Rate Limits

PlanUploads/minTransformations/minAPI Calls/min
Free101001,000
Pro1001,00010,000
EnterpriseUnlimitedUnlimitedCustom