Skip to content

Using the API

Use the Palatial API to use the Isaac Sim plugin or create SimReady 3D assets from images, text, or CAD files, track generation progress, and download results programmatically. All routes below use your API key and live under:

https://dashboard.palatial.cloud/api/v1/external/

Contact Palatial if you need a sandbox or staging environment for integration testing.


API keys are created per workspace. A key can only read and generate assets inside the workspace it was created in, and only workspace members (or organization admins) can create one. See Roles and permissions.

  1. Open the workspace in the dashboard and select the API tab next to Assets, Exports, and Team.

    The workspace API tab, showing the API Keys panel with a New key button and a Quick start example.
  2. Click New key. Give the key a name so you can recognise it later (for example the pipeline or machine that will use it). The expiration date and rate limits are optional.

    The Create API Key dialog with the name field filled in and optional expiration and rate limiting fields.
  3. Click Create API Key. The key is shown once. Copy it and store it in your secret manager now; after you close this dialog it cannot be displayed again.

    The API Key Created dialog showing an example key value, Copy and Download buttons, and a usage example.
  4. Click I’ve saved my key. The key now appears in the list with a masked value, its scope, and when it was last used. Revoke removes it immediately; requests using a revoked key return 403.

    The API tab listing one key with a masked value, its read and generate scope, last-used time, and a Revoke button.

Send the key on every request using one of:

  • Header: x-api-key: YOUR_API_KEY
  • Header: Authorization: Bearer YOUR_API_KEY
  • Query: ?api_key=YOUR_API_KEY

Never paste a key into a chat message, screenshot, public issue, or source file. If a key may have been exposed, revoke it from the API tab and create a new one.

  1. Create an asset with one of the generation endpoints (Image → Sim, Text → Sim, or CAD → Sim).
  2. Poll status until the asset is READY (or handle PROCESSING_FAILED).
  3. Download the SimReady export ZIP or individual outputs (mesh, texture, collisions, etc.).
  • Generated texture size: use texture_size=2048, 4096, or 8192 for 2K, 4K, or 8K provider-generated textures. The default is 4096 (4K).
  • Texture delivery optimization: optimize_textures=true downsizes maps above texture_max_resolution. For Meshy outputs, eligible opaque base-color maps may be delivered as high-quality JPEG sidecars while technical maps remain lossless. It never upscales smaller maps.
  • Generation modes: Image → Sim and Text → Sim take mode (diffusion or parametric), effort for Parametric (low or mad_max), and a parameters object holding only that route’s build settings. See Generation.
  • Diffusion decimation: with no decimation settings, the mesh is simplified to at most 100,000 faces. Pass decimation: false to turn it off, decimation_mode: "auto" for quality-driven simplification, or decimation_mode: "strict" with exactly one of decimation_target_faces or decimation_target_ratio. CAD omission remains disabled.
  • Asset Variants: branch a successful asset into a new independent asset by describing the desired change in feedback. Palatial chooses the rebuild work. Do not send a pipeline stage.
  • Reprocess vs Variant: POST /assets/{id}/reprocess overwrites the same asset. Sending destination: "variant" returns 400. Create a new asset with POST /assets/{id}/variants.
  • CAD reference image: optional. Omit image to skip texture generation.

Key type What you can access
Workspace API key (recommended) Assets and workspaces tied to that workspace
User-scoped key Assets you own in your workspaces
Master key (enterprise) Broader access; some calls require an explicit owner field

If you receive 403 Forbidden, check that the asset belongs to the workspace attached to your API key and that you have the required workspace access and any applicable generation balance.


Code Meaning
200 Success
201 Resource created
307 Redirect (export download , follow with -L in cURL)
400 Invalid request (check field names and values)
403 Invalid API key, insufficient permissions, or the workspace does not meet the generation or first-export credit gate
404 Asset or workspace not found
409 Request conflicts with the current resource state
500 Server error. Retry read-only polling with backoff. Do not replay a create, Variant, reprocess, or export whose outcome is unknown.
503 Temporarily unavailable, or a Variant request that created and charged nothing. Retry reads. Do not blindly replay a submission.

When you create or submit an asset, status.status moves through states like:

Status Meaning
INIT Created but not yet submitted (Text → Sim may start here briefly)
SUBMITTED Queued for processing
QUEUED Accepted, waiting to start
PROCESSING_IMPORT Generation in progress
PROCESSING_PAUSED A checkpoint between stages, or a credit pause; inspect billing.paused, billing.pauseReason, and run.awaitingContinue
READY Done , outputs are available to download
PROCESSING_FAILED Failed , check status.displayText on the asset
PROCESSING_CANCELED Canceled

Poll GET …/status every few seconds until you see READY or a terminal failure state. The status object may also include progress, completedSteps, totalSteps, and displayText for a coarse progress indicator.


Terminal window
# 1a. Create and submit - If using a Single Image
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/imagetosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@product.jpg" \
-F "name=Storage Bin" \
-F "description=A rigid plastic storage bin with a hinged lid" \
-F "mode=diffusion"
# 1b. Create and submit - If using Multiview
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/imagetosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "front=@chair_front.jpg" \
-F "left=@chair_left.jpg" \
-F "back=@chair_back.jpg" \
-F "right=@chair_right.jpg" \
-F "name=Office Chair" \
-F "description=Black mesh office chair with armrests" \
-F "mode=diffusion"
# Response includes "id" , save it as ASSET_ID
# 2. Poll until READY
curl "https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/status" \
-H "x-api-key: YOUR_API_KEY"
# 3. Download SimReady export (the first export requires a positive balance; export itself is free)
curl -L -o export.zip \
"https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/media/export" \
-H "x-api-key: YOUR_API_KEY"

Base path: /api/v1/external/assets


GET /api/v1/external/assets

Returns a paginated list of assets in your workspace. Depending on the API deployment, the JSON body is either a bare array or an object with data; handle both shapes. Asset records may include the additive billing and warnings fields. Query: pass a filter object (JSON) with optional fields:

Field Description
where.workspace Filter by workspace ID
where.search Search by name
where.status.status Filter by status (e.g. READY)
limit Page size (default 10; clamped to 1–200)
afterId Last asset ID from the previous page (24 hex characters). Cannot be combined with where.ids.
skip Offset for pagination. Ignored when afterId is set.

Results are always sorted by _id ascending. Custom sort values, including createdAt and updatedAt, do not change the order.

Terminal window
curl -G "https://dashboard.palatial.cloud/api/v1/external/assets" \
-H "x-api-key: YOUR_API_KEY" \
--data-urlencode 'filter={"limit":20}'
# Next page: replace this example ID with the last ID returned above.
curl -G "https://dashboard.palatial.cloud/api/v1/external/assets" \
-H "x-api-key: YOUR_API_KEY" \
--data-urlencode 'filter={"limit":20,"afterId":"507f1f77bcf86cd799439011"}'

GET /api/v1/external/assets/{id}

Returns the full asset record: name, type, parameters, status, export info, metadata, and (when available) billing and warnings.


POST /api/v1/external/assets

Creates a draft asset without starting generation. You must call Submit separately. Required: name, workspace Optional: description, parameters, and pipeline options. Prefer the one-shot generation endpoints with mode for a new integration.


PATCH /api/v1/external/assets/{id}

Update name, description, parameters, or other metadata on an existing asset.


POST /api/v1/external/assets/{id}/submit

Starts or restarts processing for an existing asset. Body (optional JSON):

Field Description
type Pipeline type, e.g. imagetosimready, cadtosimready
retry Retry reason string (stored on the asset)

POST /api/v1/external/assets/{id}/reprocess

Re-runs an existing asset starting from a specific pipeline stage. This keeps the same asset ID and asset type, writes reprocess controls onto the asset, and submits it for processing again. Use this when you want to regenerate one step, such as shape or texture, without creating a brand-new asset. Body (JSON):

Field Required Description
from By mode Stage key to re-run from: shape-generation, parts-gen, texture, collision-preview, physics-predictions, articulation, validation-playback. Required unless you send physics_validation_only or both keep flags below. physics is not a valid value.
mode No step stops after the requested stage; auto runs downstream stages automatically. Defaults to step.
stopAfter No Explicit stage to stop after. Defaults to from when mode is step.
sourceRunId No Exact prior product run whose artifacts should seed this reprocess.
destination No overwrite only, which is the default. Reprocess always updates the current asset in place. Sending variant returns 400. Use POST /assets/{id}/variants to create a new asset.
physics_validation_only No true keeps existing textures and shape/parts and re-runs from physics-predictions through validation (mode defaults to auto). from may be omitted.
keep_existing_textures No With keep_existing_shape=true, same as physics_validation_only.
keep_existing_shape No With keep_existing_textures=true, same as physics_validation_only.
feedback No Optional instruction for the regenerated stage. Max 4,000 characters.

Example , regenerate texture only and pause:

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/reprocess" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "from": "texture", "mode": "step" }'

Example: keep textures and shape; only physics plus validation:

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/reprocess" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "physics_validation_only": true }'

Example , regenerate from shape and continue downstream:

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/reprocess" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "from": "shape-generation", "mode": "auto" }'

Response: 200 OK , returns the queued reprocess/run response for the asset. After calling this endpoint, poll GET /api/v1/external/assets/{id}/status or GET /api/v1/external/assets/{id}/pipeline-runs/current until the asset reaches READY, PROCESSING_PAUSED, PROCESSING_FAILED, or PROCESSING_CANCELED.

Errors:

  • 400 , invalid stage key, invalid mode, missing asset workspace, or invalid reprocess request.
  • 403 , the API key does not have submit access to the asset, or the workspace has insufficient credits/limits.
  • 404 , asset not found.

GET /api/v1/external/assets/{id}/status

Returns the current processing status. Use this to poll during generation. Response fields: status, progress, completedSteps, totalSteps, displayText, timestamps, and (when available) billing. If billing.paused is true and billing.pauseReason is insufficient_credits, add tokens and keep polling. If status is PROCESSING_PAUSED while billing.paused is false and the current run has awaitingContinue: true, it is a normal checkpoint that resumes automatically.


DELETE /api/v1/external/assets/{id}/cancel-processing

Stops queued, active, or paused processing and moves the asset to PROCESSING_CANCELED. Cancellation is accepted while the asset is SUBMITTED, QUEUED, PROCESSING_IMPORT, PROCESSING_EDIT, MESH_GENERATED, TEXTURE_GENERATED, or PROCESSING_PAUSED. Repeating the request for an already canceled asset is safe.

Terminal window
curl -X DELETE \
"https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/cancel-processing" \
-H "x-api-key: YOUR_API_KEY"

Response , 200 OK:

{ "success": true }

After a successful request, poll GET /api/v1/external/assets/{id}/status until it returns PROCESSING_CANCELED. Errors:

  • 400 , the asset is not currently processing.
  • 403 , the API key does not have access to the asset.

POST /api/v1/external/assets/statuses

Body: { “ids”: [“id1”, “id2”] } Returns status and export for each ID , useful when tracking many assets.


GET /api/v1/external/assets/{id}/pipeline-runs/current

Returns per-stage progress for the current generation run (run.stages[], run.currentStageKey, and overall run status). Use this if you need stage-level detail beyond the coarse /status response. The latest stage timing, progress, and any artifacts live under run.stages[]; settled customer charges live under billing.stages[].

Palatial may merge, skip, or add stages for a route or request. Treat the returned run.stages[] and run.currentStageKey as authoritative; do not assume a fixed stage count or infer charges from a hard-coded stage list. run.stages[].tokenCost is keyed by key, while billing.stages[].tokenCost is keyed by stageKey and is the authoritative settled customer charge.


New generations, Variants, and Reprocess requests use postpaid stage billing when the response contains billing.mode: "postpaid_stage_v1":

  • No estimated total is deducted at submission.
  • Each successfully completed stage is charged once after that stage completes.
  • billing.stages[].tokenCost is the final token amount charged for that stage. Clients must not calculate it from the number of stages.
  • A same-stage replay does not duplicate an existing charge. If a new execution produces a new settled charge, the public stage value is the accumulated charge for that stage.
  • A completed stage with tokenCost: 0 is an explicit no-charge result. A missing stage charge means that no settled charge has been recorded for that execution.
  • Eligible edits include feedback, edited segmentation, and effective changes to processing settings. Their applicable stages use the 50% rate per stage; positive discounted amounts are rounded down and remain at least 1 token. Read the resulting tokenCost rather than reproducing this calculation.
  • Token balances and stage charges can be fractional for eligible discounted edits. A zero actual-cost delta falls back to the fixed stage price; when that fixed price is also zero, the receipt is no charge.

Before a new generation is admitted, the workspace’s net balance must meet the route-specific minimum below. This check admits the work; it does not reserve or deduct the entire amount.

Route Minimum balance to start
Diffusion 20 tokens
Parametric Low 40 tokens
Mad Max 80 tokens
CAD → Sim 4 tokens

The billing.warnings field is advisory and does not replace this gate. For new requests, mode=diffusion uses the Diffusion floor of 20, mode=parametric with effort=low uses 40, effort=mad_max uses 80, and CAD → Sim uses 4. Flat requests without mode use the floor of their equivalent mode. The current mid-run advisory recommendations are 10 tokens for Diffusion and 20 tokens for Parametric/Mad Max; a warning is advisory and does not reject a request that meets its route floor. CAD has no low-balance warning.

Reprocess is a continuation of an existing asset and needs a net balance above 0 rather than a new-generation route floor. Variants, drafts, and first exports use their own server-side balance gate.

If the initial gate fails, the API returns HTTP 403 with the required floor and shortfall. Clients should branch on tokens.required:

{
"statusCode": 403,
"code": "insufficient_tokens",
"error": "Insufficient tokens",
"message": "Generation start requires at least 40 tokens; balance is 12 (28 short).",
"tokens": { "required": 40, "balance": 12, "shortfall": 28 },
"correlationId": "…",
"timestamp": "…",
"path": "/api/v1/external/assets/create/texttosim"
}

Nothing is created when this gate rejects a new request. Add enough tokens to meet the route minimum, then submit once. The current minimums are an admission floor, not a whole-generation quote.

An already-running stage is allowed to finish. If its completed charge leaves the shared workspace balance at 0 or below, the next stage is held and the asset reports PROCESSING_PAUSED. For a credit pause, read billing.paused: true, billing.pauseReason: "insufficient_credits", and billing.autoResume: true.

After a purchase or subscription credit makes the net balance greater than 0, the same asset resumes automatically from its saved progress. Do not create, confirm, or retry a replacement request. A balance restored only to exactly 0 does not resume the run.

Normal stage checkpoints also report PROCESSING_PAUSED, but have billing.paused: false and run.awaitingContinue: true. Palatial’s background reconciler checks these checkpoints about once per minute and continues all eligible runs for the organization/workspace while the balance is above 0. API-key clients do not call a resume endpoint; keep polling the same asset. Only a credit pause needs a posted top-up. Resume/accept checkpoint endpoints are dashboard/JWT flows, not API-key actions.

Reprocess, Variant, draft-create, and first-export requests made while the balance is not positive can be rejected with a balance-only HTTP 403/409 with code: "insufficient_tokens" or "insufficient_credits". That is distinct from the new-generation start gate above:

{
"statusCode": 403,
"code": "insufficient_tokens",
"error": "Insufficient tokens",
"message": "Insufficient tokens for this operation.",
"reason": "insufficient_credits",
"billingMode": "postpaid_stage_v1",
"tokens": { "balance": -2 }
}

When available, create, submit, Variant, Reprocess, status, batch-status, and current-run responses include:

{
"billing": {
"mode": "postpaid_stage_v1",
"balance": {
"tokens": -2,
"planTokens": 0,
"purchasedTokens": 0,
"debtTokens": 2,
"ownerType": "organization",
"ownerId": "ORGANIZATION_ID"
},
"paused": true,
"pauseReason": "insufficient_credits",
"autoResume": true,
"canStartGeneration": false,
"stages": [
{ "stageKey": "shape-generation", "tokenCost": 10, "chargedAt": "2026-09-24T12:00:00.000Z" }
],
"warnings": []
}
}

billing.stages contains the settled charges to use for the current generation attempt. It is not a pending quote or a lifetime spend total. canStartGeneration is only a balance.tokens > 0 snapshot; the route-specific initial gate above remains authoritative for a new request. Warnings are advisory objects such as { "code": "low_recommended_balance", "recommendedTokens": 20, "balance": 12, "message": "…" } and do not replace the gate.

The usual fixed stage amounts are route-dependent and can be skipped or merged by the run. At the current stage rates, Diffusion Shape is about 9–10 tokens, Parametric Low Build model is about 45, Mad Max Build model is about 91, Parts and Texture are 1 each, Collision is 1, Physics is 0–1, Articulation is about 2 when applicable, and Playback validation is about 9. Read the returned billing.stages[]; these values are guidance, not a contract. Diffusion and Parametric Low may report a cumulative actual-cost-derived charge for their merged early stages.

Palatial can combine early work into one step. In the segmented Diffusion and Parametric routes, articulation may be skipped because the shape step already builds the joints; the current run is authoritative. For artifact lookup, process-file=articulation can return the MJCF at articulation/mjcf/model.xml; the simulator package and download package are exposed by simulator-asset and download-package. The final export ZIP uses the simulator-specific package name, such as MuJoCo_assets_<id>.zip or IsaacSim_assets_<id>.zip.


One-shot endpoints that create and submit an asset in a single call. Image → Sim and Text → Sim build with one of two modes: Diffusion or Parametric. Parametric has two efforts: Low and Mad Max. Each of the three routes honors a different set of build settings, so each has its own parameters object. CAD → Sim starts from your uploaded mesh and has no mode.

Route Request What it does Start floor
Diffusion mode: "diffusion" Generates a mesh from your photo or description, then segments, textures, and simplifies it. Fastest and cheapest. Good for organic shapes. You control structure, mesh density, and textures. 20 tokens
Parametric Low mode: "parametric", effort: "low" (the default effort) Authors a clean parametric model with its own parts. Better for manufactured objects and moving parts. You control joints, face budget, and collision. 40 tokens
Parametric Mad Max mode: "parametric", effort: "mad_max" Researches the real product, then authors the model. Decides structure, density, and appearance itself. Takes longer and costs more. 80 tokens

mode: "mad_max" is accepted as a shorthand for mode: "parametric" with effort: "mad_max".

The start floor is the balance a workspace needs before the build starts. See Billing and credit pauses for how the full cost is charged.

Every Image → Sim and Text → Sim request has the same top-level fields. mode, effort, and product_research choose the route; the build settings for that route go inside parameters. Do not also send shape_model or texture_model: mode and effort select the shape route, and Palatial selects the texture model. The controls below describe rigid assets; joints connect rigid parts. There is no body-type choice to make.

Field Required Description
name Yes Asset name, 4 to 50 characters: letters, numbers, spaces, _, -, .
description Yes What the object is, up to 500 characters. Include real dimensions when you know them.
mode Yes for new integrations diffusion or parametric. mad_max is shorthand for Parametric at effort: "mad_max".
effort No Parametric only: low (default) or mad_max.
product_research No How much research a researching build does: on (default), specs_only, or off. Accepted only where the build researches: Parametric Mad Max, and any build from a video. See Parametric Mad Max.
parameters No The build settings for that route. Omit it to use the defaults. Parametric Mad Max takes none.
engine No Target simulator: isaac_sim (default), mujoco, or newton. Diffusion and Parametric Low accept several (repeat the field, or send an array). Mad Max accepts exactly one.
workspace No Workspace ID. Defaults to the API key’s workspace.

In JSON, parameters is an object. In multipart form data (Image → Sim), send parameters as one form field holding a JSON string, for example -F 'parameters={"structure":"single_object"}'. Values inside parameters keep their JSON types: send 50000, not "50000", and true, not "true".

With mode, the request is strict:

  • A build setting the route does not honor is refused with 400 CREATE_PARAMETERS_INVALID, and the message lists the settings that route accepts.
  • A build setting sent at the top level next to mode (for example shape_model or mesh_quality) is refused with 400 CREATE_MODE_FIELD_CONFLICT. Move supported build settings into parameters; omit shape_model and texture_model.
  • effort with mode: "diffusion", or effort: "low" with mode: "mad_max", is refused with 400 CREATE_EFFORT_INVALID.
  • product_research on a route that does not research is refused with 400 CREATE_PRODUCT_RESEARCH_UNSUPPORTED.
  • parameters without mode is refused with 400 CREATE_MODE_REQUIRED.
  • With a video, research settles the build for every route, so parameters must be empty; product_research still applies. See Video.

A refused request creates and charges nothing.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/imagetosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@mug.jpg" \
-F "name=Coffee Mug" \
-F "description=A ceramic coffee mug with a rounded handle, 9 cm tall." \
-F "mode=diffusion" \
-F 'parameters={"structure":"single_object","texture_size":4096}'
Setting Default Values
structure static_parts single_object: one solid rigid mesh. static_parts: separate rigid parts with no joints. articulated_parts: parts joined by joints that rotate or slide, such as doors, drawers, and wheels.
mesh_quality high (medium for single_object) low, medium, high
triangle_count auto minimal, low, medium, high, x_high, auto
mesh_density medium low, medium, high. Used when triangle_count is auto.
decimation strict, 100,000 faces false turns simplification off. Explicit legacy true without a mode/target uses the triangle-count preset instead.
decimation_mode strict auto for quality-driven simplification, or strict with exactly one target below.
decimation_target_faces 100,000 Maximum face count, 4 to 10,000,000. Strict only.
decimation_target_ratio none Fraction of faces to keep, 0.001 to 0.999. Strict only. Do not send with decimation_target_faces.
texture_size 4096 2048, 4096, 8192
optimize_textures true Downsize maps above texture_max_resolution. Never upscales.
texture_max_resolution 4096 512, 1024, 2048, 4096, 8192
collision_quality automatic; currently medium Omit to use the default, or choose low, medium, high, sdf. See Collision selection.
run_simulation true Run physics validation after the build.
newton_solver mujoco mujoco, style3D. Read only when engine includes newton.
repair_mesh true Close holes and fix bad geometry after generation.

Limits: one photo on file, or 2 to 4 named views (front, left, back, right). Text → Sim needs no photo.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/texttosim" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Storage Cabinet",
"description": "A steel storage cabinet, 90 cm wide, 45 cm deep and 180 cm tall, with two hinged doors.",
"mode": "parametric",
"effort": "low",
"engine": ["isaac_sim", "mujoco"],
"parameters": { "articulation": true, "face_budget": 50000 }
}'
Setting Default Values
articulation false true adds joints to the model’s moving parts. false keeps the parts rigid. Parametric Low always delivers the model’s own parts, so there is no single-mesh option.
face_budget 100,000 Faces the builder authors the model to, 2,000 to 200,000.
collision_quality automatic; currently medium Omit to use the default, or choose low, medium, high, sdf. See Collision selection.
run_simulation true Run physics validation after the build.
optimize_textures true Optimize the delivered texture files.
newton_solver mujoco mujoco, style3D. Read only when engine includes newton.

Mesh quality, triangle count, density, texture size and mesh repair are not settings here: the builder authors the finished topology, textures and size itself. Low builds rigid parts. Provide real dimensions in description; omit body_type, auto_scale and replace_glass on new requests.

Limits: 1 to 50 photos on file and the named view fields, in any mix. Text → Sim needs no photo.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/imagetosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@cabinet-front.jpg" \
-F "file=@cabinet-open.jpg" \
-F "name=Storage Cabinet from Photo" \
-F "description=Match the cabinet in these photos, 90 cm wide, 45 cm deep and 180 cm tall." \
-F "mode=parametric" \
-F "effort=mad_max" \
-F "engine=isaac_sim" \
-F "product_research=specs_only"

Mad Max takes no parameters: it decides structure, joints, mesh density, and textures itself, so any build setting is refused. Collision selection is automatic: Mad Max chooses proxies appropriate to the parts, including simple proxies where appropriate. There is no collision_quality parameter on this route. The one choice left to you is the top-level product_research:

product_research What research does
on (default) Researches the real product on the web, its pages and its product photos.
specs_only Reads the web for identity and specifications only, so the model is built from your photos alone. Needs at least one photo or a video.
off Looks nothing up. Needs at least one photo or a video.

Write a useful description and, for Image → Sim, send photos that clearly identify the object.

Limits:

  • Exactly one engine.
  • Up to 8 photos, or 7 with a reference_mesh. One build takes 8 inputs and the mesh is one of them.
  • reference_mesh: an optional scanned GLB that guides the build. Mad Max only.
  • Not available on CAD → Sim.

The asset can stay in INIT while research runs. Its full record exposes parameters.agentBuildJobId; read GET /api/v1/external/mad-max/jobs/{jobId} with the same workspace key to inspect native research/build progress. A native job can fail while the asset still says INIT. Report the job error separately; do not send another create request to check progress.

Mad Max needs usable product evidence. Supply a real-product identity, product page or photo. A generic text description can return product_research_evidence_missing when research cannot retain a usable product view; that failure occurs before a 3D build starts. The same job read works for a bound video research job. In MCP 0.1.9, palatial_get_asset for INIT and palatial_get_asset_details include this as generation_job, without retrying it.

Reading results: generationAgent on the asset names the route that built it: diffusion, parametric, or mad_max. It is response metadata, not a create setting.

Use automatic selection unless your simulator or contact task needs a particular representation. Collision quality changes the collision representation and its detail, not the visible mesh or texture resolution.

Choice Diffusion and Parametric Low Tradeoff
Automatic (recommended) Omit collision_quality in the raw API. Its current default is medium. In the MCP, auto omits this override for you. Use the route’s default; Mad Max chooses proxies itself.
low Delegates convex decomposition to the target simulator rather than supplying authored hull meshes. A simpler collision policy; actual geometry and cost depend on the simulator.
medium Authored convex hulls at the standard detail preset. The usual balance of collision detail and processing cost.
high Authored hulls with a higher detail budget. More detailed collision geometry can increase hull count, generation work and contact computation.
sdf Requests signed-distance-field collision, with a hull fallback when direct SDF cannot be resolved. An explicit representation choice; support and behaviour depend on the target simulator.

Current API compatibility: the raw API does not yet accept the string auto; leave the field out. Older clients can still send x_high, but it is a legacy hull-detail preset and is omitted from the recommended controls above. Do not use the visual mesh’s triangle_count presets to choose collision quality.

SDF is not the default for an ordinary rigid asset. A simple object may be better served by a primitive or other simple proxy, such as a cylinder for a cylindrical part, when the target simulator and contact task support it. Mad Max’s automatic collision authoring can choose such proxies where appropriate. The current Diffusion/Low default is a medium hull policy; automatic selection does not promise a primitive collider for every cylinder. More hulls do not by themselves prove better simulator behaviour. Validate contacts in the target simulator for the intended task.

POST /api/v1/external/assets/create/imagetosim

Content-Type: multipart/form-data Create a SimReady asset from photos or a product video. Send name, description, mode, engine, and parameters as form fields, and the files below.

Field Description
file Product photo (PNG, JPG, JPEG, WebP). Repeat the field for several photos where the mode allows it.
front, left, back, right Named views of the same object. Diffusion needs at least 2 of them and accepts at most 4.
video One product video. See below.
reference_mesh Optional scanned GLB. Mad Max only.

Do not mix file and named views on Diffusion. Each mode’s photo limits are listed in its section above.

Send one product video on the video field, alone or with photos. At least one photo or the video is required.

Field Description
video One product video, MP4 or MOV, at most 300 MB and 60 seconds.

How a video is used:

  • Every build from a video runs Product Research on the clip first, so the request needs a useful description, and the asset can stay in INIT while research runs.
  • Diffusion builds from images, so research picks the best front, back, and side views from the video. When you also send photos, the video helps research identify the product and the build uses your photos.
  • Parametric Low and Mad Max pass the original video downstream with the research result. Parametric Low uses it to learn how the parts move.
  • Research settles structure, joints, and the other build settings from the clip, so with a video parameters must be empty on every route. The top-level product_research (on, specs_only, or off) still applies.
  • With a video, Diffusion and Parametric Low accept up to 50 photos beside it. Mad Max keeps its limit of 8.

Video errors return 400 with a code: VIDEO_FORMAT_UNSUPPORTED (not MP4 or MOV), VIDEO_EMPTY, VIDEO_UNREADABLE, or VIDEO_TOO_LONG. A video over 300 MB returns 413 VIDEO_TOO_LARGE. A refused request creates and charges nothing.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/imagetosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "file=@lamp-front.jpg" \
-F "video=@lamp.mp4" \
-F "name=Desk Lamp from Video" \
-F "description=A desk lamp with a weighted round base, a hinged two-part arm and a tilting cone shade." \
-F "mode=parametric" \
-F "effort=low" \
-F "engine=mujoco" \
-F "product_research=specs_only"

Response: 201 Created. The asset is submitted and processing begins. Save the returned id and poll its status until READY or a terminal failure.

POST /api/v1/external/assets/create/texttosim

Content-Type: application/json Send name, description, mode, effort, engine, and parameters; no image file is needed. For Diffusion and Parametric Low, Palatial first generates a reference image from the description. Mad Max researches the description instead. To send a Mad Max reference_mesh, use multipart form data instead.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/texttosim" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Articulated Storage Cabinet",
"description": "A steel storage cabinet, 90 cm wide, 45 cm deep and 180 cm tall, with two hinged doors and four internal shelves.",
"mode": "parametric",
"effort": "mad_max",
"product_research": "on",
"engine": "isaac_sim"
}'

Save the returned ID and poll /status until READY or a terminal failure; do not recreate the asset while waiting.

Compatibility for existing clients

Requests without mode are still accepted, so existing integrations keep working. In that shape the generation settings sit at the top level, and the route comes from shape_model and effort:

Flat request Equivalent route
shape_model omitted, auto, or diffusion diffusion
shape_model=parametric with effort omitted or low parametric with effort: "low"
shape_model=parametric with effort=mad_max parametric with effort: "mad_max"
Flat field Setting in parameters
enable_parts_segmentation=false Diffusion structure: "single_object"
enable_parts_segmentation=true Diffusion structure: "static_parts"
create_articulation=true Diffusion structure: "articulated_parts", Parametric Low articulation: true
decimation_mode=strict with decimation_target_faces Parametric Low face_budget
Other flat fields The setting of the same name

The flat shape is lenient: a setting the chosen route does not use is accepted and has no effect. Two flat requests are refused because they could never be built:

  • Parametric with decimation_target_ratio returns 400 PARAMETRIC_DECIMATION_REQUIRES_FACE_TARGET.
  • Parametric with decimation_target_faces outside 2,000 to 200,000 returns 400 PARAMETRIC_FACE_BUDGET_UNSUPPORTED.

New integrations should send mode and parameters. The MCP omits shape_model, texture_model, body_type, auto_scale, replace_glass and x_high collision quality; older raw API/CLI requests remain compatible.

POST /api/v1/external/assets/create/cadtosim

Content-Type: multipart/form-data Upload a CAD or mesh file and, optionally, a reference photo. Palatial normalizes the geometry, builds collision and physics, and produces a SimReady asset. Unlike Image → Sim, CAD does not run AI shape generation; it starts from your uploaded mesh. Omit image to skip texture generation (apply_textures defaults to false when no reference photo is sent).

Files:

Field Required Formats
mesh Yes STEP, STP, IGES, IGS, OBJ, GLB, GLTF, FBX, STL, PLY, USD, USDA, USDC, or USDZ
image No PNG, JPG, JPEG, WebP (reference photo)
datasheet No PDF (optional engineering datasheet)

CAD → Sim has no mode and takes its settings as top-level fields. It accepts the Diffusion settings as flat fields, using enable_parts_segmentation and create_articulation in place of structure, plus the CAD-only fields below. Not used on CAD: mesh_quality, shape_model, effort.

Field Required Default Description
enable_parts_segmentation No false Run AI part segmentation on the uploaded CAD mesh. Set true for rigid parts without joints.
create_articulation No false true for articulated parts (also forces part segmentation on)
apply_textures No true with image, otherwise false Generate textures from the reference image. Defaults off when no image is uploaded.
keep_existing_textures No — When true, do not replace textures even if an image is also sent.
regenerate_parts No false When true, regenerate parts even if the CAD file already has authored parts. Default keeps existing parts.
keep_existing_shape No — When true, do not replace existing shape or parts. Combine with keep_existing_textures for physics plus validation only. Incompatible with regenerate_parts=true.
physics_validation_only No false Skip texture and parts regeneration and run later stages. Incompatible with regenerate_parts=true.
decimation No false Backward-compatible switch. Prefer decimation_mode for new integrations.
decimation_mode No , auto for quality-driven adaptive decimation, or strict for scene-wide QEM with exactly one target.
decimation_target_faces Strict only , Hard upper face-count target from 4 to 10,000,000. Mutually exclusive with decimation_target_ratio.
decimation_target_ratio Strict only , Fraction of source faces to retain from 0.001 to 0.999. For example, 0.25 retains about 25%. Mutually exclusive with decimation_target_faces.
texture_size No 4096 Requested provider-generated texture size: 2048 (2K), 4096 (4K), or 8192 (8K).
optimize_textures No true Downscale oversized generated texture maps. For Meshy outputs, eligible opaque base-color maps may use high-quality JPEG sidecars while technical maps remain lossless.
texture_max_resolution No 4096 Maximum generated-texture long edge: 512, 1024, 2048, 4096, or 8192. Smaller maps are never upscaled.
units By format — Dashboard alias for direct-mesh scale: m, cm, mm, inch, or feet. No default. Required (or send meters_per_unit) for OBJ, GLB, GLTF, FBX, STL, and PLY. Omit for STEP, IGES, and USD.
up_direction By format — Dashboard alias for source_up_axis: x, y, or z. No default. Required for STEP, IGES, and direct mesh inputs. Omit for USD.
source_up_axis By format — Canonical source up axis (x, y, or z). Same requirement as up_direction.
meters_per_unit By format — Positive meters represented by one source unit. Canonical form of units for direct mesh inputs.
triangle_count No auto Legacy preset selector. With decimation=true, auto maps to adaptive mode and fixed presets map to strict face targets.
mesh_density No medium Only when triangle_count is auto

Decimation and source-frame behavior:

  • Source-frame fields are never defaulted or inferred. STEP and IGES require an explicit source_up_axis or matching up_direction. Direct mesh inputs require an explicit axis plus scale. USD stage metadata owns both fields, so omit them on USD uploads.
  • JT and SLDPRT are not supported.
  • Part segmentation defaults to off. Omit enable_parts_segmentation for a single-object CAD upload. Do not regenerate existing authored parts unless you pass regenerate_parts=true.
  • For new integrations, use decimation_mode=auto for target-free, quality-driven decimation; mesh_density controls the quality preset. Use decimation_mode=strict for scene-wide QEM with exactly one of decimation_target_faces or decimation_target_ratio.
  • For backward compatibility, decimation=true with triangle_count=auto maps to auto mode. Fixed presets map to strict targets: minimal = 20k, low = 50k, medium = 100k, high = 200k, and x_high = 500k faces.
  • The worker prefers GPU acceleration when available and falls back to CPU. Clients do not select a device.

Generated texture size and optimization:

  • Send one public texture_size value end to end: 2048, 4096, or 8192. The default is 4096 (4K).
  • Meshy and Hunyuan generated maps are optimized by default to a 4096px maximum long edge.
  • Optimization only downsizes oversized maps; it never upscales smaller maps. For Meshy outputs, eligible opaque base-color maps may use high-quality JPEG sidecars while normal, roughness, and metallic maps remain lossless.
  • Set texture_max_resolution=8192 for 8K delivery or optimize_textures=false to preserve provider-native maps.

Strict face-target example:

Supply the actual axis and scale of your file; this example assumes a Y-up mesh in metres.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/cadtosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "mesh=@factory-scene.glb" \
-F "image=@factory-reference.jpg" \
-F "name=Optimized Factory Scene" \
-F "description=Factory scene prepared for realtime simulation" \
-F "source_up_axis=y" \
-F "meters_per_unit=1" \
-F "apply_textures=true" \
-F "decimation_mode=strict" \
-F "decimation_target_faces=50000" \
-F "texture_size=4096" \
-F "optimize_textures=true" \
-F "texture_max_resolution=4096"

CAD without a reference photo (no texture generation):

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/cadtosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "mesh=@bracket.step" \
-F "name=Mounting Bracket" \
-F "description=Aluminum L-bracket with two mounting holes" \
-F "source_up_axis=z"

Strict retained-ratio example:

Supply the actual axis and scale of your file; this example assumes a Y-up mesh in metres.

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/create/cadtosim" \
-H "x-api-key: YOUR_API_KEY" \
-F "mesh=@factory-scene.glb" \
-F "image=@factory-reference.jpg" \
-F "name=Quarter Density Factory Scene" \
-F "description=Retain about one quarter of the source faces" \
-F "source_up_axis=y" \
-F "meters_per_unit=1" \
-F "decimation_mode=strict" \
-F "decimation_target_ratio=0.25"

POST /api/v1/external/assets/{id}/variants

Content-Type: application/json Create and submit a new independent asset from a successful source asset. The request body requires only feedback. Palatial interprets the requested difference and chooses the required regeneration work automatically. This endpoint requires a workspace API key with asset:variant-create. Named internal-service keys are not accepted.

Field Required Default Description
feedback Yes , Plain-language description of what should differ from the source asset (max 2,000 characters).
name No Generated from the request Name for the new asset (4–50 characters).
description No Source asset description Description for the new asset (max 500 characters).
parameters No Source asset settings Applicable generation settings to override. Explicit values take precedence over settings inferred from feedback.

Only the fields above are accepted. Pipeline stages, quotes, conversation references, and operation IDs are owned by Palatial. Sending from or clientOperationId returns 400. Example:

Terminal window
curl -X POST "https://dashboard.palatial.cloud/api/v1/external/assets/ASSET_ID/variants" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"feedback": "Make the mug matte blue rubber while preserving its form."
}'

A visible change may take about 30 seconds while Palatial interprets the feedback and prepares the reference image used by the build. Configure the client timeout to wait for the response. Each POST is a separate create request; do not automatically repeat a request whose outcome is unknown after a connection timeout. Response: 201 Created, returns the new asset. Save its id, then use the existing status, cancellation, and download endpoints. The example below shows selected response fields.

{
"id": "NEW_ASSET_ID",
"name": "Blue Rubber Mug",
"description": "A simulation-ready mug",
"type": "imagetosimready",
"status": { "status": "SUBMITTED" },
"requestedChange": {
"instruction": "Apply a matte blue rubber finish while preserving the form.",
"changeClasses": ["appearance"],
"referenceImage": {
"imageBase64": "...",
"mimeType": "image/jpeg"
}
}
}

requestedChange reports how the request was interpreted. The reference image is included for visible changes and contains the exact image used by the build; it is omitted when the change does not use an image. Behavior and limits:

  • The source asset is never overwritten. The returned id belongs to a new asset in the same Variant family.
  • Feedback can describe appearance, geometry, parts, collision, physics, articulation, or validation changes. Palatial chooses the required work; clients do not choose a pipeline stage.
  • Requests that cannot produce a real difference are rejected before creation and charging.
  • CAD geometry cannot be changed through feedback. Upload the modified CAD file as a new asset instead.
  • A visible change to a multiview source may be rejected when one generated reference image cannot safely replace the complete view set. Common failures:
HTTP status When it occurs
400 Missing or blank feedback, invalid values, or fields that are not part of the public contract.
403 Missing capability, invalid key, insufficient credits, or Variant creation is unavailable.
404 The source asset was not found or is outside the key workspace.
409 The source is not ready, or the requested change is unsupported or ineffective.
503 The request cannot be interpreted or prepared safely at this time. An explicit 503 response creates and charges nothing.

POST /api/v1/external/assets/generate-image

Body: { “prompt”: “…”, “articulationType”: “single_object” } Returns a preview image as base64 without creating an asset. Useful for testing prompts before a full generation run.


All paths are under /api/v1/external/assets/{id}/…. Requires x-api-key.

Method Path What you get
GET /media/export SimReady export ZIP. The first export requires a positive balance but does not charge tokens; a later run can use an earlier export only when the server still exposes its materialized export.key. Returns redirect — use curl -L.
GET /media/mesh Shape / mesh GLB
GET /media/texture Textured mesh GLB (?final_viewer=true optional)
GET /media/collisions Collision meshes
GET /media/parts Segmented parts GLB
GET /media/articulated_meshes Articulated mesh GLB
GET /media/validation-report Physics validation JSON
GET /media/image Source / preview image
POST /media/images Batch thumbnails , body { “ids”: [“…”] }
POST /media/upload-url Presigned URL to upload a mesh for editing workflows

Download intermediate outputs before READY

Section titled “Download intermediate outputs before READY”

GET /api/v1/external/assets/{id}/process-file/{process}

Check whether a pipeline stage output is ready and get a download URL.

process value Output
shape-generation Base mesh
parts-gen Segmented parts
texture Textured mesh
collision-preview Collision geometry
simulator-asset Simulator package
download-package Download package
articulation Articulated mesh
physics-predictions Physics data
validation-playback Validation artifacts

Response:

Field Meaning
state: “pending” Not ready yet , poll again
state: “found” Ready , use files[].downloadUrl
state: “skipped” Stage not applicable for this asset
state: “error” Stage failed , see reason

Intermediate outputs are route-dependent. Use pipeline-runs/current to see which stages exist for the current run before requesting a process file.


Base path: /api/v1/external/workspaces

Method Path Description
GET /workspaces List your workspaces
GET /workspaces/{id} Get workspace details (credits, plan, etc.)
GET /workspaces/{id}/members List workspace members
PATCH /workspaces/{id}/deduct-tokens Legacy export-ready acknowledgement; marks the export ready and returns {tokens}, but does not debit generation tokens or check whether a ZIP exists

Base path: /api/v1/external/users

Method Path Description
GET /users Your user profile
GET /users/{id} Profile for your user ID

Organize assets into scenes within a workspace.

Method Path Description
GET /workspaces/{workspaceId}/scenes List scenes
POST /workspaces/{workspaceId}/scenes Create scene
GET /scenes/{sceneId} Get scene
PATCH /scenes/{sceneId} Update scene
DELETE /scenes/{sceneId} Delete scene
POST /scenes/{sceneId}/assets Add asset to scene
DELETE /scenes/{sceneId}/assets/{assetId} Remove asset from scene

Store custom JSON alongside an asset (e.g. physics tuning, video URLs). Path: /api/v1/external/assets/{id}/embedded/{purpose} Supported purposes include physics and videourl.

Method Description
GET Read embedded data
POST Create or replace , body { “data”: { … } }
PATCH Update , body { “data”: { … } }
DELETE Remove embedded data

import json, os, time, requests
HOST = "https://dashboard.palatial.cloud"
H = {"x-api-key": os.environ["PALATIAL_API_KEY"]}
with open("product.jpg", "rb") as f:
resp = requests.post(
f"{HOST}/api/v1/external/assets/create/imagetosim",
headers=H,
files={"file": f},
data={
"name": "Storage Bin",
"description": "A plastic bin with hinged lid",
"mode": "diffusion",
"parameters": json.dumps({"structure": "static_parts"}),
},
)
resp.raise_for_status()
asset_id = resp.json()["id"]
while True:
st = requests.get(f"{HOST}/api/v1/external/assets/{asset_id}/status", headers=H).json()
if st["status"] == "READY":
break
if st["status"] in ("PROCESSING_FAILED", "PROCESSING_CANCELED"):
raise RuntimeError(st.get("displayText", st["status"]))
time.sleep(5)
export = requests.get(
f"{HOST}/api/v1/external/assets/{asset_id}/media/export",
headers=H,
allow_redirects=True,
)
export.raise_for_status()
with open(f"export_{asset_id}.zip", "wb") as out:
out.write(export.content)
{
"id": "…",
"name": "Storage Bin",
"type": "imagetosimready",
"status": {
"status": "READY",
"progress": 100,
"displayText": "Ready"
},
"export": {
"status": "READY",
"size": 4902028
},
"parameters": {
"engine": ["isaac_sim"],
"collision_quality": "medium",
"create_articulation": true
}
}

For API keys, workspace credits, or rate limits, please checkout the Palatial Dashboard.

Still need help?

Our team reviews every request and will get back to you as soon as possible.

Submit a request

Tell us what you're trying to do and where it went wrong. Include the asset link if you have one.