API Reference

/

Overview

API Reference Overview

The shared conventions every Moshpit endpoint follows — read this once, then jump to a specific endpoint.

Base URL

–

Plain

https://moshpit.studio

All endpoints below are relative to this base.

Authentication

Two authentication schemes:

SchemeUsed byHeaders
Secret BearerPOST /api/editor/embed-sessionsAuthorization: Bearer msk_...
Public + Secret/api/v1/* backend API callsAuthorization: Bearer msk_...  +  X-Moshpit-Public-Key: mpk_...
Session BearerAll requests from inside an embed iframeAuthorization: Bearer {sessionToken} (the JWT)

The session bearer is automatic — the SDK injects it; the iframe carries it as a query param. You only deal with the secret + public scheme when calling the API directly from your own backend.

X-Moshpit-External-User-Id

Many endpoints accept an optional X-Moshpit-External-User-Id header. Its value is your own identifier for one of your customers (an external user), not a Moshpit login. When present it scopes the request to that customer — splat reads/writes are limited to scenes that customer owns, and a minted session is scoped to them.

The header is required by the whole /api/v1/external-user surface, where it names the customer to provision, allocate, meter, or delete. See the External Users API and the reseller guide.

Plan access

All plans can mint viewer embed sessions with POST /api/editor/embed-sessions; viewer mints are unmetered. Editor Embed sessions and the /api/v1/* REST endpoints are also available on every plan.

Pro accounts can mint watermark-free viewer sessions and call /api/v1/*. Enterprise adds higher included limits and pay-as-you-go overage on storage and Scene usage. REST calls themselves are not metered.

Bearer token always wins inside an iframe

When an iframe hits a Moshpit API and the user happens to have a logged-in Moshpit Studio session, both the session JWT (Bearer) and the studio cookie arrive on the request. The Bearer header is preferred, so the embed always authenticates as the integration owner — never as the visitor.

Session token format

TS

TypeScript

{
  typ: 'moshpit_embed_session';
  sub: string; // owner ID
  identityUserId: string;
  integrationId: string;
  publicKey: string; // mpk_...
  capabilities: Array<'editor' | 'viewer'>;
  iat: number;
  exp: number; // iat + 900 seconds
}

HS256-signed JWT. 15-minute lifetime. You don't need to verify it — Moshpit does that on every request.

Error envelope

All errors share the same JSON shape:

{}

JSON

{
  "status": "error",
  "message": "Human-readable description",
  "issues": ["Optional field-level validation messages"]
}

issues is only present on 400-level validation errors.

HTTP status codes

StatusMeaning
200Success
201Created
400Bad request — JSON parse failure, schema validation, etc.
401Unauthorized — missing or invalid credentials
403Forbidden — plan, capability, or ownership check failed
404Not found — resource doesn't exist or isn't owned by your integration
410Gone — integration has been revoked
413Payload too large — quota exceeded
500Server error

404 is also returned when a resource exists but doesn't belong to your integration. This is intentional — Moshpit doesn't disclose existence.

CORS

The /api/v1/* endpoints allow cross-origin calls:

–

Plain

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, X-Moshpit-Public-Key, X-Moshpit-External-User-Id, Content-Type

OPTIONS preflight requests succeed for any origin.

CORS does not protect your secret

CORS controls which browsers may call the API. It does not make the secret safe to expose. Browsers can still send any header they want from page JS. Always proxy /api/v1/* calls through your own backend on user-facing sites — the secret never goes near the browser.

Endpoint catalog

MethodPathUse
POST/api/editor/embed-sessionsMint a viewer or editor session token
POST/api/v1/uploads/splat-fileCreate a signed upload URL
POST/api/v1/uploads/lod-folderCreate signed LOD-folder upload URLs
POST/api/v1/uploads/splat-imagesCreate signed thumbnail/depth URLs
POST/api/v1/splatsCommit an uploaded Scene
GET/api/v1/splatsList Integration Splats
GET/api/v1/splats/{splatId}Fetch one splat with levelData
POST/api/v1/splats/{splatId}/cloneDuplicate or remix a scene
PUT/api/v1/external-userProvision or update a reseller customer
GET/api/v1/external-userFetch one customer's record
GET/api/v1/external-user/usagePer-customer usage and allocation
DELETE/api/v1/external-userSoft-delete a customer and their scenes

Paginated list responses use JSON body metadata. See the Pagination Guide for cursor, numbered page, and offset examples.

Rate limits

There are no per-endpoint request-rate limits documented today. REST calls and viewer session mints are not metered. Treat the API as best-effort and design for retries with exponential backoff on 5xx.

What's next