Skip to main content

Backend API Reference

.NET 9.0 Web API built with Clean Architecture and Domain-Driven Design (DDD) principles.

For AI Agents

This documentation is designed for AI agents to quickly understand the backend structure and locate code.

Base URL

  • Development: http://localhost:5009
  • Docker (HTTP): http://localhost:8080
  • Docker (HTTPS): https://localhost:8081

Quick Reference

Model Upload & Management (10 endpoints)

MethodEndpointDescription
POST/modelsUpload new 3D model
POST/models/{modelId}/filesAdd file to existing model
POST/models/{modelId}/tagsUpdate model tags/description
GET/modelsList all models (?packId, ?projectId)
GET/models/{id}Get model details
GET/models/{id}/fileDownload model file
PUT/models/{id}/defaultTextureSetSet default texture for version
POST/models/{id}/active-version/{versionId}Set active version
DELETE/models/{id}Soft delete model
DELETE/models/{modelId}/versions/{versionId}Soft delete version

Model Versions (6 endpoints)

MethodEndpointDescription
POST/models/{modelId}/versionsCreate new version
POST/models/{modelId}/versions/{versionId}/filesAdd file to version
GET/models/{modelId}/versionsList all versions
GET/models/{modelId}/versions/{versionId}Get version details
GET/models/{modelId}/versions/{versionId}/fileDownload renderable file
GET/models/{modelId}/versions/{versionId}/files/{fileId}Download specific file

Files (1 endpoint)

MethodEndpointDescription
GET/files/{id}Download any file by ID

Thumbnails (4 endpoints)

MethodEndpointDescription
GET/models/{id}/thumbnailGet thumbnail status
POST/models/{id}/thumbnail/regenerateQueue thumbnail regeneration
POST/models/{id}/thumbnail/uploadUpload custom thumbnail
GET/models/{id}/thumbnail/fileDownload thumbnail image

Texture Sets (14 endpoints)

MethodEndpointDescription
GET/texture-setsList all texture sets
GET/texture-sets/{id}Get texture set details
GET/texture-sets/by-file/{fileId}Get texture set containing a file
POST/texture-setsCreate new texture set (JSON)
POST/texture-sets/with-fileCreate texture set with file upload
PUT/texture-sets/{id}Update texture set
DELETE/texture-sets/{id}Soft delete texture set
DELETE/texture-sets/{id}/hardHard delete (keeps files)
POST/texture-sets/{id}/texturesAdd texture to set
DELETE/texture-sets/{packId}/textures/{textureId}Remove texture from set
PUT/texture-sets/{setId}/textures/{textureId}/typeChange texture type
POST/texture-sets/{packId}/model-versions/{modelVersionId}Associate with model version
DELETE/texture-sets/{packId}/model-versions/{modelVersionId}Disassociate from model version
POST/texture-sets/{packId}/models/{modelId}/all-versionsAssociate with all model versions

Recycled Files (4 endpoints)

MethodEndpointDescription
GET/recycledList all recycled items
POST/recycled/{entityType}/{entityId}/restoreRestore recycled item
GET/recycled/{entityType}/{entityId}/previewPreview delete impact
DELETE/recycled/{entityType}/{entityId}/permanentPermanently delete

Worker API - Thumbnail Jobs (3 endpoints)

MethodEndpointDescription
POST/api/thumbnail-jobs/dequeueDequeue next job (workers only)
POST/api/thumbnail-jobs/{jobId}/completeMark job complete (workers only)
POST/api/test/thumbnail-complete/{modelId}Test completion notification (dev)

Total: 42 endpoints

Architecture Overview

The backend follows Clean Architecture with strict layer separation:

WebApi → Application → Domain ← Infrastructure
↓ ↑
SharedKernel ← ← ← ← ↑

Key Files

WhatWhere
API Endpointssrc/WebApi/Endpoints/*.cs
Commands/Queriessrc/Application/*/
Domain Entitiessrc/Domain/Models/*.cs
Repository Interfacessrc/Application/Abstractions/Repositories/
Repository Implementationssrc/Infrastructure/Data/Repositories/
DI Registrationsrc/*/DependencyInjection.cs

Texture Types

Albedo, Normal, Metallic, Roughness, AmbientOcclusion, Emissive, Height, Opacity

Error Handling

Errors are returned as JSON with error.code and error.message.

Read-Only Query Pattern for Specialized Components

Specialized infrastructure components (WebDAV, Blender addon layer) that need complex data graphs should query DbContext directly rather than using shared repositories.

Why?

  • Repositories stay lean - Frontend calls don't over-fetch data
  • Specialized queries - Each component crafts exactly the includes it needs
  • Read-only optimization - Use AsNoTracking() for performance
  • Self-contained - Optimizations don't affect other consumers

Pattern

// In specialized infrastructure component (e.g., VirtualAssetStore)
private async Task<Project?> GetProjectWithFullAssetGraph(IServiceProvider sp, string name)
{
var dbContext = sp.GetRequiredService<ApplicationDbContext>();

return await dbContext.Projects
.AsNoTracking() // Read-only, no change tracking
.Include(p => p.Models)
.ThenInclude(m => m.Versions)
.ThenInclude(v => v.Files)
.Include(p => p.Sounds)
.ThenInclude(s => s.File)
.AsSplitQuery() // Prevent cartesian explosion
.FirstOrDefaultAsync(p => p.Name == name);
}

When to Use

Use CaseApproach
Frontend API endpointsUse repositories (lean queries)
WebDAV virtual file systemDirect DbContext with full includes
Blender addon data exportDirect DbContext with full includes
Write operationsAlways use repositories

Key Rules

  1. Read-only access only - Never modify entities fetched this way
  2. Always use AsNoTracking() - Since we're not tracking changes
  3. Use AsSplitQuery() - When including multiple collections to avoid cartesian products
  4. Keep in Infrastructure layer - This pattern is for Infrastructure components, not Application layer