# Flash-3D Agent API Reference

> Project Repo: https://github.com/freakynit/flash-3d

Autonomous 3D modeling API for AI agents. Direct HTTP/JSON interface to in-memory Three.js engine.
- Target URL: Use user-provided server URL if specified; otherwise fallback to `http://localhost:3001`.
- Coordinate System: Right-handed (Three.js): +Y up, +X right, +Z forward (towards viewer). Lengths in consistent units.
- Transforms: Local to parent. `position:[x,y,z]`, `rotation:[rx,ry,rz]` (Euler XYZ in degrees unless `useRadians:true`), `scale:[sx,sy,sz]|number`. Accepted inside `params.transform` OR directly at top level of `params`.

## Autonomous Agent Workflow

1. Resolve URL: `BASE = user_url or "http://localhost:3001"`.
2. Clear / Reset: Start workflow or batch with `CLEAR_SCENE` (or `POST /api/scene/clear`).
3. Construct Model: Send single `POST /api/batch` containing all parts, materials, CSG, and transforms (`summary: "compact"`, `stopOnError: true`).
4. Validate Bounds: Check `res.success === true`. Check `res.sceneSummary.bounds` (`size`, `min`, `max`) to verify spatial footprint. On error, inspect `res.error` / `res.data.results`.
5. Export Asset: Fetch `GET /api/export/glb` (binary) or `gltf` (JSON) and save file to disk.

```python
# Autonomous Agent Client Snippet (Python stdlib)
import urllib.request, json
BASE = "http://localhost:3001" # override with user URL if provided
def api(ep, data=None):
    req = urllib.request.Request(f"{BASE}{ep}", data=json.dumps(data).encode() if data else None, headers={"Content-Type":"application/json"} if data else {})
    with urllib.request.urlopen(req) as r: return r.read() if "/export/" in ep else json.loads(r.read())

# 1-call build & export example:
res = api("/api/batch", {"actions": [{"action": "CLEAR_SCENE"}, {"action": "CREATE_BOX", "params": {"id": "box1", "width": 2, "height": 1, "depth": 2, "material": {"preset": "metal"}}}], "summary": "compact"})
if res.get("success"):
    with open("model.glb", "wb") as f: f.write(api("/api/export/glb"))
```

## Transport & Endpoints

| Endpoint | Method | Payload / Params | Description |
|---|---|---|---|
| `POST /api/action` | POST | `{action, params, summary?}` | Execute single action. Returns Standard Response. |
| `POST /api/batch` | POST | `{actions:[{action,params},...], stopOnError:true, summary:"compact"}` | Sequential execution (prior successes persist on error). Data: `{total, succeeded, failed, results:[...]}`. |
| `GET /api/scene` | GET | none | Returns `{success:true, data:sceneJSON, sceneSummary}`. |
| `GET /api/catalog` | GET | none | Returns `{actions:[...], materialPresets:[...]}`. |
| `GET /api/docs` | GET | none | Returns this markdown API reference. |
| `GET /api/export/:format` | GET | `?id=optionalObjectId` | Stream download: `:format` in `glb` (binary, recommended), `gltf`, `obj`, `stl`, `json`. Prefer over EXPORT_SCENE. |
| `POST /api/import` | POST | `{format:"obj"|"stl"|"json", data, id?, transform?, material?, encoding?}` | Import 3D model (`encoding:"base64"` for binary STL). |
| `POST /api/scene/clear` | POST | `{keepLights:true, keepCamera:true}` | Deletes user objects. |
| `POST /api/scene/reset` | POST | `{}` | Clears all objects, animations, and restores default camera/lights. |
| `/ws` | WS | `{action,params}` or `{type:"BATCH",actions:[...]}` | Real-time WebSocket sync. |

### Standard Response Shape
```json
{
  "success": true,
  "action": "CREATE_BOX",
  "targetId": "box1",
  "message": "Box 'box1' created successfully.",
  "data": { "id": "box1" },
  "error": null,
  "suggestion": null,
  "sceneSummary": {
    "objectCount": 1, "totalVertices": 24, "totalTriangles": 12,
    "bounds": { "min": [-1, -0.5, -1], "max": [1, 0.5, 1], "size": [2, 1, 2] }
  },
  "executionTimeMs": 2
}
```
`summary` options: `"compact"` (bounds & counts only, recommended for speed/tokens), `"full"` (includes `objects:[...]`), `"none"` (`sceneSummary: null`).

## Shared Creation & Material Parameters

- `id`: Optional unique string. Auto-generated (`obj_1`, `box_1`...) if omitted. Case-sensitive.
- `transform`: `{position:[x,y,z], rotation:[x,y,z], scale:[x,y,z]|number, useRadians:false}`. Can also place `position`, `rotation`, `scale` directly in `params`.
- `material`: Object with preset or custom properties:
  - Presets: `default`, `plastic`, `metal`, `gold`, `silver`, `copper`, `chrome`, `glass`, `wood`, `stone`, `clay`, `rubber`, `neon`, `water`. (Preset properties can be overridden).
  - Basic: `color` (`"#rrggbb"`), `roughness` (0..1, def:0.5), `metalness` (0..1, def:0.1), `opacity` (0..1, def:1), `transparent` (bool), `wireframe` (bool), `flatShading` (bool), `side` (`"front"`|`"back"`|`"double"`).
  - Physical: `emissive` (`"#rrggbb"`), `emissiveIntensity` (def:1), `transmission` (0..1, clear glass: 0.9, opacity:1), `ior` (def:1.5), `thickness`, `clearcoat`, `clearcoatRoughness`.
  - External Texture Files (PNG, JPEG/JPG, data URIs, base64, URLs; auto-embedded in glTF/GLB):
    - Diffuse / Base Color Map: `texturePath` (e.g. `"exports/moon_1024.jpg"` or relative/absolute path), `textureUrl` (HTTP/HTTPS URL), `textureData` (base64 string / Data URI), or `map`.
    - PBR Map Channels: `normalMapPath` (or `normalMap`), `roughnessMapPath`, `metalnessMapPath`, `emissiveMapPath`, `bumpMapPath`, `aoMapPath`, `alphaMapPath`.
    - Texture Controls: `textureRepeat: [x,y]|number`, `textureOffset: [x,y]`, `textureRotation: number` (radians), `textureWrap: "repeat"|"clamp"|"mirror"`, `normalScale: [x,y]|number`, `bumpScale: number`.
    - Image filtering: decoded PNG/JPEG textures use linear magnification and trilinear mipmapped minification to reduce distant-surface aliasing. These sampler settings are preserved in glTF/GLB exports; no extra API parameters are required.
  - Procedural Textures (in-memory canvas, embedded in glTF/GLB): `textureType` (`"checkerboard"`|`"stripes"`|`"grid"`|`"noise"`|`"wood"`|`"brick"`|`"dots"`), `textureScale` (def:8), `textureColor1` (hex), `textureColor2` (hex).

## Geometry Actions

Notation: `key=default`. Bare keys are required. All accept shared creation params (`id`, `transform`, `material`).

| Action | Parameters & Defaults | Spatial Alignment & Notes |
|---|---|---|
| `CREATE_BOX` | `width=1, height=1, depth=1, widthSegments=1, heightSegments=1, depthSegments=1, bevel=0, bevelSegments=2` | Centered at origin. `bevel>0` creates rounded machined edges (bevel clamped to min(w,h,d)/2). |
| `CREATE_SPHERE` | `radius=1, widthSegments=32, heightSegments=16, phiStart=0, phiLength=2π, thetaStart=0, thetaLength=π` | Centered at origin. Phi/theta in radians. |
| `CREATE_CYLINDER` | `radius=1` (or `radiusTop=1, radiusBottom=1`), `height=2, radialSegments=32, heightSegments=1, openEnded=false` | Centered along Y axis ($Y \in [-h/2, +h/2]$). |
| `CREATE_CONE` | `radius=1, height=2, radialSegments=32, heightSegments=1, openEnded=false` | Apex along +Y axis, base at $Y = -h/2$. |
| `CREATE_TORUS` | `radius=1, tube=0.4, radialSegments=16, tubularSegments=48, arc=360` | In XY plane. `arc` in degrees. |
| `CREATE_TORUS_KNOT` | `radius=1, tube=0.4, p=2, q=3, tubularSegments=64, radialSegments=16` | Torus knot in XY/Z. |
| `CREATE_CAPSULE` | `radius=0.5, length=1, capSegments=8, radialSegments=16` | Aligned along Y axis. Total height = `length + 2*radius`. |
| `CREATE_PLANE` | `width=2, height=2, widthSegments=1, heightSegments=1` | Flat in XY plane (normal +Z). Double-sided by default. |
| `CREATE_CIRCLE` | `radius=1, segments=32` | Flat circle in XY plane. Double-sided by default. |
| `CREATE_RING` | `innerRadius=0.5, outerRadius=1, thetaSegments=32, phiSegments=1` | Flat ring in XY plane. Double-sided by default. |
| `CREATE_POLYHEDRON` | `type="icosahedron"` (or `"dodecahedron"|"octahedron"|"tetrahedron"`), `radius=1, detail=0` | Centered regular polyhedron. |
| `EXTRUDE_SHAPE` | `shape:[[x,y],...]` (>=3 pts), `holes:[[[x,y],...],...]`, `depth=1, steps=1, bevelEnabled=false, bevelThickness=0.1, bevelSize=0.1, bevelOffset=0, bevelSegments=3` | 2D profile extruded along +Z axis from Z=0 to `depth`. Outer shape CCW, holes CW. |
| `LATHE_SHAPE` | `points:[[radius,y],...]` (>=2 pts), `segments=32, phiStart=0, phiLength=360` | Revolve 2D half-cross-section around Y axis. `radius >= 0`. Phi in degrees. Best for vases, bottles, glasses, columns, bowls, domes. |
| `CREATE_TUBE` | `path:[[x,y,z],...]` (>=2 pts), `radius=0.2, tubularSegments=64, radialSegments=12, closed=false, curveType="catmullrom"` (or `"linear"`) | Sweeps circular cross-section along 3D path. Best for pipes, wires, handles, rails. |
| `CREATE_CUSTOM_MESH` | `vertices:[x,y,z,...]`, `indices:[i,j,k,...]`, `uvs:[u,v,...]`, `normals:[x,y,z,...]` | Raw indexed/unindexed triangle mesh. CCW front winding. Flat or nested arrays. |
| `CREATE_HEIGHTMAP` | `width=10, depth=10, widthSegments=30, depthSegments=30, maxHeight=2, heights:[...]` | Grid terrain on XZ plane. If `heights` omitted, generates procedural organic terrain. |
| `BOOLEAN_UNION` | `targetA, targetB, id?, keepOriginals=false, material?` | Solid CSG union (A + B). World-space result. Consumes inputs unless `keepOriginals:true`. |
| `BOOLEAN_SUBTRACT` | `targetA, targetB, id?, keepOriginals=false, material?` | Solid CSG difference (A - B). Cut cavity B from A. Cutter B must slightly overlap/protrude beyond A's faces to prevent coplanar errors. |
| `BOOLEAN_INTERSECT` | `targetA, targetB, id?, keepOriginals=false, material?` | Solid CSG intersection (A ∩ B). Overlapping volume only. |

## Assembly, Modification & Hierarchy

| Action | Parameters & Defaults | Description |
|---|---|---|
| `SET_TRANSFORM` | `id, position?, rotation?, scale?, useRadians=false` | Sets local transform values. |
| `TRANSLATE` | `id, offset:[dx,dy,dz]` | Adds offset in parent coordinates. |
| `ROTATE` | `id, rotation:[rx,ry,rz], useRadians=false` | Adds Euler rotation angles (degrees by default). |
| `SCALE` | `id, scale:number|[sx,sy,sz]` | Multiplies current scale. |
| `ALIGN_OBJECT` | `id, ground=false, targetY=0, alignX="center"|"min"|"max", alignZ="center"|"min"|"max"` | Aligns object world bounds. `ground:true` (or `alignY:"ground"|"min"`) snaps minY to `targetY`. |
| `CLONE_OBJECT` | `id, newId?, transform?` | Creates independent deep copy of mesh & material at scene root. |
| `ARRAY_MODIFIER` | `id, count=3, offset=[1,0,0], rotation=[0,0,0], scale=[1,1,1], useRadians=false, groupIntoParent=false, parentId?` | Spawns `count` copies named `id_item_1`..`count` with step `i*offset`, `i*rot`, `scale^i`. |
| `DEFORM_MESH` | `id, operation="twist"|"bend"|"taper"|"wave"|"noise", factor=1.0, axis="y"` (`"x"|"z"`) | Vertex deformation along axis. Twist/bend factor in rad/unit. |
| `SUBDIVIDE_MESH` | `id` | Splits each triangle into 4 (retains vertex attributes; flat tessellation). |
| `GROUP_OBJECTS` | `id?, memberIds:[...], transform?` | Preserves member world transforms, parents them into new Group. Empty group serves as animation pivot. |
| `PARENT_OBJECT` | `id, parentId, keepWorld=false` | Parents `id` under `parentId`. `keepWorld:true` preserves world transform. Cycles rejected. |
| `UNPARENT_OBJECT` | `id` | Attaches `id` to scene root preserving world transform. |
| `DELETE_OBJECT` | `id` | Deletes object, descendant subtree, and associated animation tracks. |
| `CLEAR_SCENE` | `keepLights=true, keepCamera=true` | Clears user objects. |
| `RESET_SCENE` | none | Restores blank scene, default lights/camera, clears animations. |
| `SET_MATERIAL` | `id, ...materialFields` | Updates/patches existing object material (preset + overrides, including `texturePath`, `normalMapPath`, etc.). |
| `SET_COLOR` | `id, color:"#hex"` | Fast shortcut to update diffuse color only. |
| `SET_TEXTURE` | `id, texturePath?, textureUrl?, textureData?, mapType="map", repeat?, offset?, rotation?, wrap="repeat", remove=false` | Loads/applies external texture file (PNG, JPEG) or clears texture (`remove:true`). `mapType`: `"map"|"normalMap"|"roughnessMap"|"metalnessMap"|"emissiveMap"|"bumpMap"|"aoMap"|"alphaMap"`. |
| `INSPECT_OBJECT` | `id` | Returns transform, world bounds, vertex/triangle counts, parent, children. |
| `GET_SCENE` | none | Returns scene environment, camera, and full summary. |

## Animation

`SET_ANIMATION`: Creates or replaces a named animation clip:
```json
{
  "name": "spin",
  "duration": 4.0,
  "tracks": [
    {
      "id": "propeller",
      "property": "rotation",
      "interpolation": "linear",
      "times": [0.0, 1.0, 2.0, 3.0, 4.0],
      "values": [[0,0,0], [0,0,90], [0,0,180], [0,0,270], [0,0,360]]
    }
  ]
}
```
- `property`: `"position"`, `"rotation"`, or `"scale"`.
- `interpolation`: `"linear"` or `"step"`.
- `times`: Strictly increasing non-negative seconds (>= 2 keyframes).
- Rotation Rule: Euler degrees `[rx,ry,rz]`, converted to quaternion shortest-path slerp. Consecutive keyframe rotations MUST be < 180° apart (e.g. 0°, 90°, 180°, 270°, 360° for a full turn).
- Loop Closure: Final keyframe value should equal initial keyframe value for seamless cycles.
- Export: Animations export cleanly into `.glb` and `.gltf`.
- `DELETE_ANIMATION`: `{ "name": "clipName" }`.

## Lighting, Environment & Camera

- `CREATE_LIGHT`: `{ id?, type="point"|"directional"|"spot"|"ambient"|"hemisphere", color="#ffffff", intensity=1, position:[x,y,z], target:[x,y,z], castShadow=false, distance=0, decay=2, angle=60, penumbra=0.1, groundColor="#444444" }`. (`angle` in degrees for spot).
- `UPDATE_LIGHT`: `{ id, color?, intensity?, distance?, decay?, angle?, penumbra?, castShadow?, position?, groundColor?, target? }`.
- `SET_ENVIRONMENT`: `{ backgroundColor?, ambientColor?, ambientIntensity?, showGrid?, showAxes?, fogColor?, fogNear?, fogFar?, fog:false }`.
- `SET_CAMERA`: `{ position:[x,y,z], target:[x,y,z], fov=50, orthographic=false }`.
- `FOCUS_OBJECT`: `{ id? }` (frames object, or whole scene if omitted).

## Import & Export

- Export: Prefer `GET /api/export/{glb|gltf|obj|stl|json}?id={optionalId}` directly to a local file.
  - `glb`: Binary glTF with embedded textures, hierarchy, and animations (recommended).
  - `gltf`: JSON glTF with embedded base64 textures and animations.
  - `obj` / `stl`: Pure geometry (no materials/animations).
  - `json`: Three.js Object JSON.
  - Action `EXPORT_SCENE`: `{ format="gltf", targetId? }` returns base64 in response payload.
- Import: `POST /api/import` or `IMPORT_MODEL`: `{ format:"obj"|"stl"|"json", data, id?, transform?, material?, encoding? }`. (glTF import is not supported).
- Texture Upload: `POST /api/texture/upload`: `{ filename: "name.jpg", data: "base64..." }` saves to `exports/` and returns `{ path, url }`. Static assets in `exports/` are served at `/exports/*`.

## Autonomous Spatial Math & Modeling Patterns

1. Stacking Formula: Primitives are centered at local origin. A box of height $H$ spans $Y \in [-H/2, +H/2]$.
   - Grounding: Set `position: [0, H/2, 0]` or run `ALIGN_OBJECT {id, ground: true}`.
   - Stacking $B$ on $A$: $Y_B = Y_A + (H_A / 2) + (H_B / 2)$.
2. Circular Distribution ($N$ items on radius $R$):
   - For $i \in [0..N-1]$, angle $\theta = i \cdot \frac{2\pi}{N}$.
   - Position: $X = R \cos\theta, Z = R \sin\theta$. Rotation: $Y = -i \cdot \frac{360}{N}$ deg.
3. CSG Difference (Cavities & Holes):
   - Make the cutter object slightly oversized ($+0.05$ radius, $+0.2$ height) and extend through both sides of the surface to prevent non-manifold zero-thickness coplanar artifacts.
4. Revolutions & Cross-Sections:
   - Use `LATHE_SHAPE` for any rotationally symmetric object (cups, bowls, bottles, wheels, pillars, domes). Points: `[[radius, y],...]` with $radius \ge 0$.
   - Use `EXTRUDE_SHAPE` for custom 2D silhouettes (wings, brackets, gears, stars, logos).
5. Pivots & Articulation:
   - Create an empty group at the joint pivot (`GROUP_OBJECTS {id: "elbow_pivot", memberIds: [], transform: {position: [px,py,pz]}}`), parent the link to it, and animate/rotate `"elbow_pivot"`.
