WIA-ART-001 Digital Art Standard - Developer Integration Guide
The API Interface specification defines how developers and systems interact with the WIA-ART-001 Digital Art Standard. Building upon the data format foundation established in Phase 1, Phase 2 provides the programmatic interfaces necessary for creating, validating, managing, and distributing digital artworks in compliance with the standard.
The API layer serves as the bridge between the abstract specification and practical implementation. Whether you're building a creative tool, a digital asset management system, or a marketplace platform, understanding these interfaces is essential for proper integration. The design philosophy follows REST principles while providing SDK abstractions for common programming languages.
The WIA-ART-001 API is designed around the principle of progressive disclosure—simple operations remain simple, while advanced features are available for those who need them. Every endpoint follows predictable patterns, making the API intuitive for developers of all experience levels.
This chapter covers the complete API ecosystem, including the TypeScript SDK, REST endpoints, authentication mechanisms, error handling patterns, and best practices for integration. Each section builds upon the previous, creating a comprehensive guide for developers implementing WIA-ART-001 support in their applications.
The WIA-ART-001 API follows a layered architecture designed for flexibility, scalability, and ease of integration. Understanding this architecture helps developers choose the right integration approach for their specific use case.
| Layer | Purpose | Components |
|---|---|---|
| Presentation | Developer-facing interfaces | SDKs, CLI tools, Web Console |
| API Gateway | Request routing and management | Load balancer, rate limiter, auth |
| Service | Business logic implementation | Validation, processing, storage |
| Data | Persistence and retrieval | Metadata DB, file storage, cache |
Developers can integrate with WIA-ART-001 through multiple approaches, each suited to different scenarios:
Production: https://api.wia.org/art-001/v1
Staging: https://staging-api.wia.org/art-001/v1
Development: https://dev-api.wia.org/art-001/v1
Regional Endpoints:
- Americas: https://us-api.wia.org/art-001/v1
- Europe: https://eu-api.wia.org/art-001/v1
- Asia: https://asia-api.wia.org/art-001/v1
The TypeScript SDK provides the most comprehensive and developer-friendly way to integrate WIA-ART-001. It includes full type definitions, automatic validation, and built-in error handling.
# npm
npm install @wia/art-001-sdk
# yarn
yarn add @wia/art-001-sdk
# pnpm
pnpm add @wia/art-001-sdk
export interface DigitalArtConfig {
// Authentication
apiKey?: string;
oauthToken?: string;
// Connection settings
endpoint?: string;
version?: string;
timeout?: number;
retryAttempts?: number;
// Feature flags
enableValidation?: boolean;
enableCaching?: boolean;
enableCompression?: boolean;
// Logging and debugging
logLevel?: 'debug' | 'info' | 'warn' | 'error';
onRequest?: (request: Request) => void;
onResponse?: (response: Response) => void;
}
// Default configuration
const defaultConfig: DigitalArtConfig = {
endpoint: 'https://api.wia.org/art-001/v1',
version: '1.0',
timeout: 30000,
retryAttempts: 3,
enableValidation: true,
enableCaching: true,
enableCompression: true,
logLevel: 'warn'
};
export class DigitalArtSDK {
private config: DigitalArtConfig;
private httpClient: HttpClient;
private cache: CacheManager;
constructor(config: DigitalArtConfig) {
this.config = { ...defaultConfig, ...config };
this.httpClient = new HttpClient(this.config);
this.cache = new CacheManager();
}
// Artwork CRUD Operations
async create(data: ArtworkInput): Promise;
async read(id: string): Promise;
async update(id: string, data: Partial): Promise;
async delete(id: string): Promise;
// Validation Operations
async validate(data: any): Promise;
async validateFile(file: File): Promise;
// Export Operations
async export(id: string, options: ExportOptions): Promise;
async exportBatch(ids: string[], options: ExportOptions): Promise;
// Search and Query
async search(query: SearchQuery): Promise;
async list(options: ListOptions): Promise;
// Metadata Operations
async getMetadata(id: string): Promise;
async updateMetadata(id: string, metadata: Partial): Promise;
// Provenance Operations
async getProvenance(id: string): Promise;
async addProvenanceEvent(id: string, event: ProvenanceEvent): Promise;
}
// Core artwork types
export interface Artwork {
id: string;
version: string;
metadata: ArtworkMetadata;
content: ArtworkContent;
provenance: ProvenanceChain;
createdAt: Date;
updatedAt: Date;
}
export interface ArtworkMetadata {
title: string;
creator: CreatorInfo;
description?: string;
creationDate: Date;
medium: string;
dimensions?: Dimensions;
colorSpace: ColorSpace;
keywords?: string[];
license?: LicenseInfo;
}
export interface ArtworkContent {
primary: ContentFile;
derivatives?: ContentFile[];
preview?: ContentFile;
thumbnail?: ContentFile;
}
export interface ContentFile {
format: SupportedFormat;
url: string;
hash: string;
size: number;
quality: QualityTier;
}
export type SupportedFormat = 'PNG' | 'JPEG' | 'TIFF' | 'WEBP' | 'SVG' | 'PSD' | 'AI';
export type QualityTier = 'archival' | 'professional' | 'web' | 'preview';
export type ColorSpace = 'sRGB' | 'Adobe RGB' | 'ProPhoto RGB' | 'Display P3';
The REST API provides direct HTTP access to all WIA-ART-001 functionality. Each endpoint follows consistent patterns for request/response formats, error handling, and pagination.
/api/v1/digital-art
Creates a new digital artwork resource with metadata and optional content files.
Request:
POST /api/v1/digital-art
Content-Type: application/json
Authorization: Bearer <api-key>
{
"title": "Ethereal Landscapes #42",
"creator": {
"name": "Artist Name",
"identifier": "artist-uuid-or-orcid",
"contact": "artist@example.com"
},
"description": "A digital exploration of liminal spaces...",
"creationDate": "2025-01-15T10:30:00Z",
"medium": "Digital painting",
"dimensions": {
"width": 4096,
"height": 3072,
"unit": "pixels",
"ppi": 300
},
"colorSpace": "Adobe RGB",
"keywords": ["landscape", "digital", "surreal"],
"license": {
"type": "CC-BY-4.0",
"commercialUse": true,
"attribution": "Required"
}
}
Response: 201 Created
{
"success": true,
"data": {
"id": "art_2xK9mN3pQr5tV7wY",
"status": "created",
"uploadUrl": "https://upload.wia.org/...",
"expiresAt": "2025-01-15T11:30:00Z"
}
}
/api/v1/digital-art/validate
Validates artwork data against the WIA-ART-001 specification without creating a resource.
Request:
POST /api/v1/digital-art/validate
Content-Type: application/json
{
"metadata": { ... },
"content": { ... }
}
Response: 200 OK
{
"valid": true,
"complianceLevel": "full",
"checks": [
{ "rule": "metadata.title.required", "passed": true },
{ "rule": "metadata.colorSpace.valid", "passed": true },
{ "rule": "content.format.supported", "passed": true },
{ "rule": "content.bitDepth.minimum", "passed": true }
],
"recommendations": [
"Consider adding ICC profile for color accuracy",
"EXIF metadata available but not included"
]
}
/api/v1/digital-art/{id}
Response: 200 OK
{
"id": "art_2xK9mN3pQr5tV7wY",
"version": "1.0",
"metadata": {
"title": "Ethereal Landscapes #42",
"creator": { ... },
"creationDate": "2025-01-15T10:30:00Z",
...
},
"content": {
"primary": {
"format": "PNG",
"url": "https://cdn.wia.org/...",
"hash": "sha256:abc123...",
"size": 15728640,
"quality": "archival"
}
},
"provenance": {
"events": [
{
"type": "creation",
"timestamp": "2025-01-15T10:30:00Z",
"actor": "artist-uuid"
}
]
}
}
/api/v1/digital-art/{id}
Request:
PUT /api/v1/digital-art/art_2xK9mN3pQr5tV7wY
Content-Type: application/json
{
"metadata": {
"description": "Updated description...",
"keywords": ["landscape", "digital", "surreal", "ethereal"]
}
}
Response: 200 OK
{
"success": true,
"data": {
"id": "art_2xK9mN3pQr5tV7wY",
"version": "1.1",
"updatedAt": "2025-01-16T14:20:00Z"
}
}
/api/v1/digital-art/{id}
Response: 200 OK
{
"success": true,
"message": "Resource deleted successfully",
"deletedAt": "2025-01-16T15:00:00Z"
}
/api/v1/digital-art?query=...
Query Parameters:
- q: Full-text search query
- creator: Filter by creator ID
- format: Filter by file format
- colorSpace: Filter by color space
- dateFrom: Creation date start (ISO 8601)
- dateTo: Creation date end (ISO 8601)
- limit: Results per page (default: 20, max: 100)
- offset: Pagination offset
- sort: Sort field (created, updated, title)
- order: Sort order (asc, desc)
Example:
GET /api/v1/digital-art?q=landscape&format=PNG&colorSpace=sRGB&limit=10
Response: 200 OK
{
"results": [...],
"pagination": {
"total": 42,
"limit": 10,
"offset": 0,
"hasMore": true
}
}
The WIA-ART-001 API supports multiple authentication methods to accommodate various integration scenarios, from simple API key usage to complex OAuth flows.
// Header-based (recommended)
Authorization: Bearer wia_art_sk_1234567890abcdef
// Query parameter (not recommended for production)
GET /api/v1/digital-art?api_key=wia_art_sk_1234567890abcdef
// Authorization Code Flow
1. Redirect user to:
https://auth.wia.org/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_CALLBACK_URL
&response_type=code
&scope=art:read art:write
2. Exchange code for token:
POST https://auth.wia.org/oauth/token
{
"grant_type": "authorization_code",
"code": "AUTH_CODE",
"redirect_uri": "YOUR_CALLBACK_URL",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET"
}
3. Use access token:
Authorization: Bearer ACCESS_TOKEN
| Scope | Description | Endpoints |
|---|---|---|
art:read | Read artwork metadata and content | GET /digital-art/* |
art:write | Create and update artworks | POST, PUT /digital-art/* |
art:delete | Delete artworks | DELETE /digital-art/* |
art:validate | Validate artwork data | POST /digital-art/validate |
art:export | Export artwork in various formats | GET /digital-art/*/export |
provenance:read | Read provenance chain | GET /digital-art/*/provenance |
provenance:write | Add provenance events | POST /digital-art/*/provenance |
{
"header": {
"alg": "RS256",
"typ": "JWT",
"kid": "wia-art-001-key-v1"
},
"payload": {
"iss": "https://auth.wia.org",
"sub": "user_id_or_client_id",
"aud": "https://api.wia.org/art-001",
"exp": 1705330800,
"iat": 1705327200,
"scope": "art:read art:write",
"org": "organization_id"
}
}
The API uses consistent error responses across all endpoints, making it easy to implement robust error handling in client applications.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "metadata.colorSpace",
"issue": "Invalid color space value",
"expected": "sRGB | Adobe RGB | ProPhoto RGB | Display P3",
"received": "RGB"
}
],
"requestId": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z",
"documentation": "https://docs.wia.org/art-001/errors#VALIDATION_ERROR"
}
}
| Code | Meaning | Common Causes |
|---|---|---|
| 200 | Success | Request completed successfully |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid JSON, missing required fields |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Resource already exists |
| 422 | Unprocessable | Validation failed |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Internal server error |
| 503 | Unavailable | Service temporarily unavailable |
// Common error codes
AUTHENTICATION_REQUIRED - No authentication provided
INVALID_API_KEY - API key is invalid or expired
INSUFFICIENT_PERMISSIONS - Scope doesn't allow this action
RESOURCE_NOT_FOUND - Requested resource doesn't exist
VALIDATION_ERROR - Request data failed validation
RATE_LIMIT_EXCEEDED - Too many requests
FILE_TOO_LARGE - Uploaded file exceeds size limit
UNSUPPORTED_FORMAT - File format not supported
INVALID_COLOR_SPACE - Color space not recognized
METADATA_INCOMPLETE - Required metadata missing
DUPLICATE_RESOURCE - Resource with this ID already exists
import { DigitalArtSDK, WIAError, ValidationError } from '@wia/art-001-sdk';
const sdk = new DigitalArtSDK({ apiKey: 'your-key' });
try {
const artwork = await sdk.create(data);
} catch (error) {
if (error instanceof ValidationError) {
console.log('Validation failed:', error.details);
error.details.forEach(detail => {
console.log(` ${detail.field}: ${detail.issue}`);
});
} else if (error instanceof WIAError) {
console.log('API Error:', error.code, error.message);
if (error.isRetryable) {
// Implement retry logic
}
} else {
throw error; // Re-throw unexpected errors
}
}
Rate limiting protects the API infrastructure and ensures fair usage across all consumers.
| Tier | Requests/Hour | Burst Limit | File Upload/Day |
|---|---|---|---|
| Free | 1,000 | 50/minute | 100 MB |
| Pro | 10,000 | 200/minute | 10 GB |
| Enterprise | 100,000 | 1,000/minute | Unlimited |
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 850
X-RateLimit-Reset: 1705330800
X-RateLimit-RetryAfter: 120
async function makeRequestWithRetry(request, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await makeRequest(request);
} catch (error) {
if (error.status === 429) {
const retryAfter = error.headers['x-ratelimit-retryafter'] || 60;
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await sleep(retryAfter * 1000);
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded');
}
Practical examples demonstrating common integration patterns.
import { DigitalArtSDK } from '@wia/art-001-sdk';
import fs from 'fs';
const sdk = new DigitalArtSDK({ apiKey: process.env.WIA_API_KEY });
async function uploadArtwork(filePath, metadata) {
// Step 1: Create artwork resource
const createResult = await sdk.create({
title: metadata.title,
creator: metadata.creator,
description: metadata.description,
colorSpace: 'Adobe RGB'
});
// Step 2: Upload file to signed URL
const fileBuffer = fs.readFileSync(filePath);
await sdk.uploadFile(createResult.uploadUrl, fileBuffer);
// Step 3: Finalize upload
await sdk.finalizeUpload(createResult.id);
// Step 4: Verify and get full artwork data
const artwork = await sdk.read(createResult.id);
console.log('Artwork created:', artwork.id);
return artwork;
}
// Usage
uploadArtwork('./artwork.png', {
title: 'My Digital Artwork',
creator: { name: 'Artist Name' },
description: 'A beautiful digital creation'
});
async function validateMultipleArtworks(artworks) {
const results = await Promise.all(
artworks.map(artwork =>
sdk.validate(artwork)
.then(result => ({ artwork, valid: true, result }))
.catch(error => ({ artwork, valid: false, error }))
)
);
const valid = results.filter(r => r.valid);
const invalid = results.filter(r => !r.valid);
console.log(`Validated: ${valid.length} valid, ${invalid.length} invalid`);
return { valid, invalid };
}
async function exportAllFormats(artworkId) {
const formats = ['PNG', 'JPEG', 'WEBP', 'TIFF'];
const exports = {};
for (const format of formats) {
exports[format] = await sdk.export(artworkId, {
format,
quality: format === 'TIFF' ? 'archival' : 'professional',
embedMetadata: true,
embedIccProfile: true
});
}
return exports;
}
Accessible APIs benefit all developers - making powerful tools available to everyone advances our collective creative potential.