API Reference

/

PATCH /v1/splats/{id}

PATCH /api/v1/splats/{splatId}

Update the title, description, or visibility of a splat owned by the supplied external user — or toggle the integration-level featured flag on any splat of the integration.

PATCH

https://moshpit.studio/api/v1/splats/{splatId}

Auth

For metadata updates (title, description, visibility) all three headers are required — those fields only mutate splats owned by the external user identified in the request:

–

Plain

Authorization: Bearer msk_YOUR_SECRET_KEY
X-Moshpit-Public-Key: mpk_YOUR_PUBLIC_KEY
X-Moshpit-External-User-Id: YOUR_HOST_USER_ID

The splat must belong to the same embedIntegrationId as the keys, and its externalUserId must match the header value. Otherwise the response is 404 (we never reveal whether a splat exists outside of the caller's scope).

featured is different: it is a curation act by the integration, not the splat owner, so it authenticates with the key pair alone (the external-user header is optional and ignored for scoping) and works on any splat of the integration — including splats owned by your end users. See Featuring a splat.

REST API access

REST API access is included on Free, Pro, and Enterprise. Storage, Scene counts, and integration limits still apply.

Body

{}

JSON

{
  "title": "Updated title",
  "description": "Optional new description",
  "visibility": "public"
}
FieldTypeDescription
title
string

Trimmed; 1–200 characters. Optional.

description
string

Up to 2000 characters. Pass `""` to clear. Optional.

visibility
"private" | "public"

New visibility. Optional.

featured
boolean

Integration-level curation flag. Must be the ONLY field in the request body. Optional.

At least one field must be present. Omitted fields are left untouched. featured cannot be combined with the other fields in one request — they use different authority scopes.

Example request

SH

Bash

curl -X PATCH "https://moshpit.studio/api/v1/splats/65f1a2b3c4d5e6f7a8b9c0d1" \
  -H "Authorization: Bearer msk_YOUR_SECRET_KEY" \
  -H "X-Moshpit-Public-Key: mpk_YOUR_PUBLIC_KEY" \
  -H "X-Moshpit-External-User-Id: host_user_123" \
  -H "Content-Type: application/json" \
  -d '{"title":"Living room — final","visibility":"public"}'

Success response — 200 OK

Returns the updated splat in the same shape as a list-splats item:

{}

JSON

{
  "status": "success",
  "splat": {
    "id": "65f1a2b3c4d5e6f7a8b9c0d1",
    "title": "Living room — final",
    "description": "Optional new description",
    "imageUrl": "https://...",
    "splatUrl": "https://...",
    "visibility": "public",
    "allowEmbed": true,
    "allowComments": true,
    "allowReactions": true,
    "allowClone": false,
    "remixedFrom": null,
    "splatType": "lod",
    "externalUserId": "host_user_123",
    "productSlug": "moshpit.studio",
    "isOwner": true,
    "viewCount": 42,
    "likeCount": 3,
    "fileSizeBytes": 17825792,
    "createdAt": "2026-04-12T18:30:00.000Z",
    "updatedAt": "2026-05-19T11:02:14.000Z"
  }
}

Featuring a splat

Mark a splat for your product's curated surfaces (for example a gallery's Featured rail). Send featured as the sole body field; the external-user header is not required:

SH

Bash

curl -X PATCH "https://moshpit.studio/api/v1/splats/65f1a2b3c4d5e6f7a8b9c0d1" \
  -H "Authorization: Bearer msk_YOUR_SECRET_KEY" \
  -H "X-Moshpit-Public-Key: mpk_YOUR_PUBLIC_KEY" \
  -H "Content-Type: application/json" \
  -d '{"featured":true}'

Rules:

  • Only public splats with allowEmbed: true can be featured — otherwise the response is 409.
  • Featuring is idempotent: re-featuring an already-featured splat keeps its original featuredAt, so curation order is stable.
  • {"featured":false} clears the flag at any time.
  • Fetch the curated set with GET /v1/splats?featured=true&sort=featuredAt&dir=desc.

Error responses

StatusCause
400Invalid JSON body, no updatable fields supplied, validation failure, or featured combined with other fields
401Missing or invalid Bearer / public-key combination
403Plan doesn't include cloning quota re-check on first publish (plan_limit)
404Scene not found OR not owned by the supplied external user (metadata updates) / not in the integration (featured)
409featured: true on a scene that is private or has embedding disabled
413Storage quota exceeded on first publish (STORAGE_QUOTA_EXCEEDED)

Publishing a clone for the first time re-checks quota

A clone created by POST /v1/splats/{splatId}/clone doesn't count against the account's maxSplats or the external user's per-customer scene cap while it stays private and unpublished. The first PATCH that sets visibility: "public" on that clone re-checks both limits and can return the same 403 plan_limit (dimension: "splatCount") or 413 STORAGE_QUOTA_EXCEEDED response a fresh upload would. Once published, the slot is consumed permanently — unpublishing it again does not free it back up.

What's next