DX.GL

Integration Guide

Markdown MCP for Video

Build 3D rendering into your product with the DX.GL pipeline

Contents
Why IntegrateArchitecture OverviewQuick Start: REST APIQuick Start: MCP PathCommon Integration PatternsTags for Multi-Tenant OrganizationCredit ManagementAsset DeliveryRender Settings ReferenceError HandlingFurther Reading

Why Integrate

Your users need product videos, turntable animations, or multi-view training datasets — but building a GPU rendering pipeline is a multi-year engineering effort. DX.GL handles the hard parts: model processing, GPU scheduling, shadow accumulation, video encoding, and asset delivery. You focus on your product.

What this means in practice:

Whether you're building an e-commerce platform, a 3D marketplace, a research data pipeline, or a content management system — the same API powers all of these.


Architecture Overview

Authentication

You use a single API key (dxgl_sk_...) created in the Portal → API Keys. All renders, uploads, and downloads are billed to your account. You handle user mapping and billing on your side however you want.

Two Integration Paths

Path Best for How it works
REST API Production pipelines, backend services Direct HTTP calls from your server. Deterministic, testable, fully scriptable.
MCP (Model Context Protocol) Prototyping, ad-hoc tasks, AI-powered workflows AI agents call DX.GL tools via natural language. Great for internal tooling and rapid iteration.

Both paths use the same underlying API and the same credit system. Many integrators start with MCP for prototyping and add direct REST calls for production.

Credit Accounting

Credits are deducted per render based on quality tier:

Quality Output Credits
standard 1080p H.264 MP4 1
4k 4K H.264 MP4 4
pro 4K ProRes 4444 with alpha 16
dataset 100×800 100-view training ZIP 1
dataset 196×1024 196-view training ZIP 4
dataset 400×2048 400-view training ZIP 16

Use the quote endpoint to check costs before committing. Batch renders deduct atomically — if you don't have enough credits, nothing is charged.


Quick Start: REST API

Base URL: https://api.dx.gl/v1

All requests require Authorization: Bearer dxgl_sk_... in the header.

1. Upload a model

curl -X POST https://api.dx.gl/v1/models \
  -H "Authorization: Bearer dxgl_sk_..." \
  -F "[email protected]" \
  -F 'renderSettings={"aspect":"16:9","bgColor":"#ffffff","length":6}'

Response:

{ "data": { "modelId": "Ab3kF9x2qL1m", "renderId": "Xz7pQ4w8nR2k" } }

The upload triggers a free system preview render automatically. If you pass renderSettings, a paid render is also queued.

2. Ingest from URL (no file upload)

curl -X POST https://api.dx.gl/v1/models/ingest \
  -H "Authorization: Bearer dxgl_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-cdn.com/model.glb", "renderSettings": {"aspect":"16:9"}}'

Same response format. The server downloads the file directly (max 100 MB, 2-minute timeout). SHA-256 deduplication prevents re-uploading identical files.

3. Create additional renders

curl -X POST https://api.dx.gl/v1/renders \
  -H "Authorization: Bearer dxgl_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "modelId": "Ab3kF9x2qL1m",
    "renderSettings": {
      "quality": "standard",
      "aspect": "1:1",
      "bgColor": "#000000",
      "length": 9,
      "shadows": true,
      "easing": true
    }
  }'

4. Batch render (multiple variants at once)

curl -X POST https://api.dx.gl/v1/renders/batch \
  -H "Authorization: Bearer dxgl_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "renders": [
      { "modelId": "Ab3kF9x2qL1m", "renderSettings": { "aspect": "16:9", "bgColor": "#ffffff" } },
      { "modelId": "Ab3kF9x2qL1m", "renderSettings": { "aspect": "1:1", "bgColor": "#000000" } },
      { "modelId": "Ab3kF9x2qL1m", "renderSettings": { "aspect": "9:16", "bgColor": "#ffffff" } }
    ]
  }'

Maximum 100 renders per batch. Credits deducted atomically. Renders for the same model share GPU frames — encoding multiple variants from one render pass.

5. Poll for completion

curl https://api.dx.gl/v1/renders/Xz7pQ4w8nR2k \
  -H "Authorization: Bearer dxgl_sk_..."

Status progression: pendingposter-processingposter-donevideo-processingdone

The poster is available at poster-done — you can show it to users immediately while the video finishes encoding.

6. Download assets

# Full video
curl -o video.mp4 https://api.dx.gl/v1/renders/Xz7pQ4w8nR2k/video \
  -H "Authorization: Bearer dxgl_sk_..."

# Web-optimized variant (lower bitrate, faster loading)
curl -o web.mp4 "https://api.dx.gl/v1/renders/Xz7pQ4w8nR2k/video?quality=web" \
  -H "Authorization: Bearer dxgl_sk_..."

# Poster image (full resolution)
curl -o poster.png "https://api.dx.gl/v1/renders/Xz7pQ4w8nR2k/poster?quality=full" \
  -H "Authorization: Bearer dxgl_sk_..."

# All assets as ZIP
curl -o assets.zip https://api.dx.gl/v1/renders/Xz7pQ4w8nR2k/bundle \
  -H "Authorization: Bearer dxgl_sk_..."

All asset endpoints return Cache-Control: immutable — renders never change after completion. Safe to cache aggressively.

Python Example

import requests, time

API = "https://api.dx.gl/v1"
HEADERS = {"Authorization": "Bearer dxgl_sk_..."}

def render_model(glb_path, settings):
    """Upload a model, render it, return the video URL."""
    with open(glb_path, "rb") as f:
        r = requests.post(f"{API}/models", headers=HEADERS,
            files={"file": f},
            data={"renderSettings": json.dumps(settings)})
    data = r.json()["data"]
    render_id = data["renderId"]

    # Poll until done
    while True:
        r = requests.get(f"{API}/renders/{render_id}", headers=HEADERS)
        status = r.json()["data"]["status"]
        if status == "done":
            return f"{API}/renders/{render_id}/video"
        if status == "error":
            raise Exception(f"Render failed: {r.json()['data'].get('errorMessage')}")
        time.sleep(3)

# Usage
url = render_model("chair.glb", {"aspect": "16:9", "bgColor": "#ffffff", "length": 6})

Node.js Example

const API = 'https://api.dx.gl/v1';
const headers = { 'Authorization': 'Bearer dxgl_sk_...' };

async function renderModel(filePath, settings) {
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  form.append('renderSettings', JSON.stringify(settings));

  const upload = await fetch(`${API}/models`, { method: 'POST', headers, body: form });
  const { renderId } = (await upload.json()).data;

  // Poll until done
  while (true) {
    await new Promise(r => setTimeout(r, 3000));
    const res = await fetch(`${API}/renders/${renderId}`, { headers });
    const { status, errorMessage } = (await res.json()).data;
    if (status === 'done') return `${API}/renders/${renderId}/video`;
    if (status === 'error') throw new Error(`Render failed: ${errorMessage}`);
  }
}

Quick Start: MCP Path

The MCP server lets AI agents interact with DX.GL through tool calls. Add this to your MCP client configuration (Windsurf, Claude Desktop, Cursor, or any compatible host):

{
  "mcpServers": {
    "dxgl": {
      "serverUrl": "https://mcp.dx.gl/",
      "headers": {
        "Authorization": "Bearer dxgl_sk_..."
      }
    }
  }
}

Available Tools

Tool Description
ingest_model Import a 3D model from a URL
list_models List models with tag and pagination filters
get_model Get model details and all its renders
create_render Create a single render (video or dataset)
create_batch_renders Create multiple renders atomically (max 100)
get_render Check render status (poll until done)
download_render Get download URL for a completed render
get_account Check credit balance
quote Estimate credit cost before committing

Example Prompts

Catalog onboarding:

Import all GLB files from these URLs, tag them "client-acme", then render each in 16:9 white and 1:1 black with shadows. Quote the total first.

Variant expansion:

For all models tagged "client-acme", create 9:16 renders with the branded gradient background (overlay ID abc123DEF456). Skip any that already have a 9:16 render.

Dataset generation:

Generate 196×1024 hemisphere datasets for all models tagged "training-batch-7". Quote first, then proceed.

Status check:

How many credits do I have left? List all pending renders and their status.

When to Use MCP vs REST

Use MCP when... Use REST when...
Prototyping a new integration Running in production
Ad-hoc batch operations Automated backend pipeline
Internal tooling for ops User-facing render triggers
Exploring the API interactively Deterministic, testable code

Many teams use both: MCP for operations and internal tooling, REST for the production path.


Common Integration Patterns

Catalog Sync

Upload new SKUs nightly from your product database. Tag each upload with a client or campaign identifier for easy filtering.

for sku in new_skus:
    r = requests.post(f"{API}/models/ingest", headers=HEADERS, json={
        "url": sku["glb_url"],
        "renderSettings": {"aspect": "16:9", "bgColor": "#ffffff", "length": 6}
    })
    model_id = r.json()["data"]["modelId"]
    # Tag the model
    requests.patch(f"{API}/models/{model_id}", headers=HEADERS, json={
        "title": sku["name"],
        "sku": sku["sku_code"],
        "tags": ["client-acme", "fall-2026"]
    })

On-Demand Rendering

User uploads a model through your UI → your backend forwards it to DX.GL → polls for completion → delivers the video.

User → Your Frontend → Your Backend → DX.GL API → Poll → Deliver video URL

The poster is available at poster-done status — show it immediately as a preview while the video finishes.

Variant Matrix

Generate every combination of aspect ratio, background, and quality for each model:

variants = [
    {"aspect": "16:9", "bgColor": "#ffffff", "shadows": True},
    {"aspect": "1:1", "bgColor": "#000000", "shadows": True},
    {"aspect": "9:16", "bgColor": "#ffffff", "reflector": True},
]

renders = []
for model_id in model_ids:
    for v in variants:
        renders.append({"modelId": model_id, "renderSettings": v})

# Submit all at once (max 100 per batch)
for batch in chunks(renders, 100):
    r = requests.post(f"{API}/renders/batch", headers=HEADERS, json={"renders": batch})

Background Image Branding

Upload your client's branded background once, then reference it across all renders:

# Upload the background image
curl -X POST https://api.dx.gl/v1/overlays \
  -H "Authorization: Bearer dxgl_sk_..." \
  -F "[email protected]" \
  -F "layer=background" \
  -F "name=Acme Brand Gradient"

# Use it in renders
curl -X POST https://api.dx.gl/v1/renders \
  -H "Authorization: Bearer dxgl_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"modelId": "...", "renderSettings": {"bgImageId": "overlay_id_here", "aspect": "16:9"}}'

The image is scaled to cover the output dimensions and cropped from the top-left anchor, keeping logos safe across all aspect ratios.


Tags for Multi-Tenant Organization

Tags are the key to organizing models across clients, projects, and campaigns. Every model can have up to 20 tags (lowercased, trimmed).

Tagging Strategy

client-{name}per-client isolation (client-acme, client-widgets-inc) campaign-{name}per-campaign grouping (campaign-fall-2026) batch-{id}per-import-batch tracking status-{state}workflow state (status-pending-review, status-approved)

Filtering

# List all models for a specific client
curl "https://api.dx.gl/v1/models?tags=client-acme&limit=100" \
  -H "Authorization: Bearer dxgl_sk_..."

# List models matching any of multiple tags (OR filter)
curl "https://api.dx.gl/v1/models?tags=client-acme,campaign-fall-2026" \
  -H "Authorization: Bearer dxgl_sk_..."

Per-Client Billing

Tag every model with the client name. To calculate spend per client, list their models, count their renders, multiply by credit cost per quality tier. The quote endpoint can help estimate future costs.


Credit Management

Check Balance

curl https://api.dx.gl/v1/account \
  -H "Authorization: Bearer dxgl_sk_..."

# Response: { "data": { "credits": 847 } }

Quote Before Committing

curl -X POST https://api.dx.gl/v1/quote \
  -H "Authorization: Bearer dxgl_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"renders": [{"quality": "standard"}, {"quality": "standard"}, {"quality": "4k"}]}'

# Response: { "data": { "creditsRequired": 6, "creditsAvailable": 847, "sufficient": true } }

Always quote large batches before submitting. The quote is free and returns per-item breakdown, total cost, and whether you have enough credits.

Monitoring

Build a simple dashboard that checks GET /v1/account periodically and alerts when credits drop below a threshold. Contact us for volume pricing at scale.


Asset Delivery

Public Share URLs

Every completed render has a public share page at https://dx.gl/portal/v/{renderId}. No authentication required for viewing. Useful for sharing with stakeholders or embedding in emails.

Direct Download

All asset endpoints support Range headers for streaming and return Cache-Control: immutable. Assets per render:

Endpoint Format Use case
GET /v1/renders/:id/video MP4 or MOV (Pro) Full-quality download
GET /v1/renders/:id/video?quality=web MP4 (lower bitrate) Web embedding, streaming
GET /v1/renders/:id/poster?quality=full PNG Product page hero, social sharing
GET /v1/renders/:id/poster PNG (thumbnail) Grid previews, hover states
GET /v1/renders/:id/thumb MP4 (quarter res) Hover video preview
GET /v1/renders/:id/bundle ZIP Bulk download of all assets

Embedding

The web video variant is optimized for <video> tags:

<video autoplay loop muted playsinline>
  <source src="https://api.dx.gl/v1/renders/{id}/video?quality=web" type="video/mp4">
</video>

Render Settings Reference

Field Type Default Description
quality string "standard" "standard" (1080p), "4k" (4K), "pro" (4K ProRes with alpha)
aspect string "16:9" "16:9", "1:1", "9:16"
bgColor string "#ffffff" Any 6-digit hex (ignored when bgImageId is set)
bgImageId string Overlay asset ID for background image
length integer 6 Duration in seconds (3–30)
shadows boolean true Ground shadows
reflector boolean false Reflective ground plane
easing boolean true Smooth rotation start/stop
rotateY integer 0 Starting angle (−180° to 180°)
tiltX integer 0 Forward/back tilt (−90° to 90°)
effect string "turntable" Camera motion: "turntable", "hero-spin", "showcase", "zoom-orbit", "reveal"
output string "video" "video" or "dataset"
datasetQuality string "100x800", "196x1024", "400x2048" (when output is dataset)
coverage string "hemisphere" "hemisphere" or "sphere" (dataset only)

Error Handling

All errors return a consistent format:

{
  "error": {
    "code": "no_credits",
    "message": "No render credits remaining",
    "status": 402
  }
}

Key error codes for integrators:

Code Status Action
unauthorized 401 Check API key
no_credits 402 Purchase more credits or contact for volume pricing
file_too_large 400 File exceeds 100 MB — reduce before upload
invalid_format 400 Only GLB, glTF, and ZIP (OBJ+MTL) are supported
model_not_found 404 Model was deleted or ID is wrong
too_many 400 Batch exceeds 100 renders — split into smaller batches
upload_limit 429 Free upload limit reached — purchase credits to unlock

Further Reading