{"openapi":"3.1.0","info":{"title":"MakeSplat API","summary":"Turn any video into a 3D Gaussian Splat (.ply) with a REST API","description":"MakeSplat turns a video of any subject (a room, an object, a scene, drone footage) into a 3D Gaussian Splat. Upload one MP4 or MOV video (up to 500 MB) and download a standard Gaussian splat `.ply` file, usually about 10 minutes later.\n\n**Base URL:** `https://api.makesplat.com`\n\n**Authentication:** send your API key on every `/v1` request as `Authorization: Bearer sk_live_...`. Create keys in your dashboard: https://makesplat.com/dashboard/keys\n\n**Flow (4 calls):**\n\n1. `POST /v1/scans` reserves a scan and returns `job_id` and a presigned `upload_url` (valid 1 hour).\n2. `PUT` the raw video bytes to `upload_url` (no Authorization header).\n3. `POST /v1/scans/{job_id}/start` charges credits and starts processing (`402` if your balance is too low).\n4. Poll `GET /v1/scans/{job_id}` until `status` is `done`, then download the `.ply` from `ply_url` (valid 24 hours).\n\n`POST /v1/scans/estimate` prices custom parameters before you start. There are no webhooks: poll for status.\n\n**Rate limits (per user, per minute):** 10 starts, 30 reserves, 120 reads, 60 file deletions. Over the limit you get `429`.\n\n**Pricing:** a standard splat costs 1 credit and your first one is free. Failed scans are refunded automatically. Credit packs: https://makesplat.com/pricing\n\n**Docs and guides:** https://makesplat.com/docs","termsOfService":"https://makesplat.com/terms","contact":{"name":"MakeSplat","url":"https://makesplat.com/docs","email":"nelsonsalvadorzx@gmail.com"},"version":"1.0.0"},"servers":[{"url":"https://api.makesplat.com"}],"paths":{"/v1/scans/estimate":{"post":{"tags":["scans"],"summary":"Estimate the credit cost of a scan","description":"Credit cost for the given parameters. Free, creates nothing.","operationId":"estimate_v1_scans_estimate_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateResponse"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"bearerAuth":[]}]}},"/v1/scans":{"post":{"tags":["scans"],"summary":"Reserve a scan and get an upload URL","description":"Reserve a scan and get a presigned upload URL. No credits charged yet.","operationId":"create_scan_v1_scans_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreateResponse"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limit exceeded. Wait a minute and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]}]},"get":{"tags":["scans"],"summary":"List your scans","operationId":"list_scans_v1_scans_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/JobOut"},"title":"Response List Scans V1 Scans Get"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limit exceeded. Wait a minute and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]}],"description":"Your scans, newest first. Page with `limit` (1 to 100, default 20) and `offset`."}},"/v1/scans/{job_id}/start":{"post":{"tags":["scans"],"summary":"Start processing an uploaded video","description":"Validates the parameters, charges credits and queues the scan. 402 if your balance is too low.","operationId":"start_scan_v1_scans__job_id__start_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStartRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStartResponse"}}}},"400":{"description":"The video has not been uploaded to `upload_url` yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Not enough credits for this scan. Buy credits and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No scan with this id on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The scan is in a state that does not allow this action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The video is larger than 500 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limit exceeded. Wait a minute and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Temporary upstream failure. You were not charged; retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]}]}},"/v1/scans/{job_id}":{"get":{"tags":["scans"],"summary":"Get a scan's status and download URL","operationId":"get_scan_v1_scans__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobOut"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No scan with this id on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limit exceeded. Wait a minute and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]}],"description":"Status is one of `created`, `queued`, `processing`, `done`, `failed`, `cancelled`. A scan you reserve but never start stays `created`. While processing, `stage` and `progress` (0 to 99) show rough progress. When `status` is `done`, `ply_url` is a signed download link for the `.ply`, valid 24 hours (each call returns a fresh one). Status updates about every 30 seconds, so poll every 30 to 60 seconds."},"delete":{"tags":["scans"],"summary":"Cancel a scan","description":"Cancel a scan that has not finished. Charged credits are refunded.","operationId":"cancel_scan_v1_scans__job_id__delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStartResponse"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No scan with this id on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The scan is in a state that does not allow this action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"bearerAuth":[]}]}},"/v1/scans/{job_id}/files":{"delete":{"tags":["scans"],"summary":"Delete a scan's stored files","description":"Permanently delete a finished scan's files: input video, .ply, preview and error log.\n\n409 while the scan is queued or processing. The job record stays (status,\nparams, credits) with files_deleted_at set; ply_url is null from then on.\nRepeating the call is safe.","operationId":"delete_scan_files_v1_scans__job_id__files_delete","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobOut"}}}},"401":{"description":"Missing, malformed or revoked API key. Send `Authorization: Bearer sk_live_...`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No scan with this id on your account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The scan is in a state that does not allow this action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limit exceeded. Wait a minute and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Temporary upstream failure. You were not charged; retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"bearerAuth":[]}]}}},"components":{"schemas":{"EstimateRequest":{"properties":{"steps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Steps","description":"Training steps, 1000 to 30000 (default 15000). More steps cost more credits."},"num_frames":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Frames","description":"Frames sampled from the video, 30 to 300 (default 120)."},"downscale":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Downscale","description":"Image downscale factor: 1 (full resolution), 2 (default) or 4. Full resolution costs more credits."},"matching":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matching","description":"Camera matching: `sequential` (default), `vocab_tree` or `exhaustive`. The last two cost more credits."}},"type":"object","title":"EstimateRequest"},"EstimateResponse":{"properties":{"credits":{"type":"string","title":"Credits"},"params":{"additionalProperties":true,"type":"object","title":"Params"}},"type":"object","required":["credits","params"],"title":"EstimateResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobCreateResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"upload_url":{"type":"string","title":"Upload Url"},"thumb_upload_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumb Upload Url"},"expires_in_seconds":{"type":"integer","title":"Expires In Seconds"}},"type":"object","required":["job_id","upload_url","expires_in_seconds"],"title":"JobCreateResponse"},"JobOut":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"status":{"type":"string","title":"Status"},"ply_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ply Url"},"web_ply_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Web Ply Url"},"thumb_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thumb Url"},"params":{"additionalProperties":true,"type":"object","title":"Params","default":{}},"error_msg":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Msg"},"elapsed_sec":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Elapsed Sec"},"ply_size_mb":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ply Size Mb"},"stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage"},"progress":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Progress"},"credits_charged":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credits Charged"},"files_deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Files Deleted At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["job_id","status","created_at","updated_at"],"title":"JobOut"},"JobParams":{"properties":{"steps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Steps","description":"Training steps, 1000 to 30000 (default 15000). More steps cost more credits."},"num_frames":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Frames","description":"Frames sampled from the video, 30 to 300 (default 120)."},"downscale":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Downscale","description":"Image downscale factor: 1 (full resolution), 2 (default) or 4. Full resolution costs more credits."},"matching":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matching","description":"Camera matching: `sequential` (default), `vocab_tree` or `exhaustive`. The last two cost more credits."}},"type":"object","title":"JobParams"},"JobStartRequest":{"properties":{"params":{"anyOf":[{"$ref":"#/components/schemas/JobParams"},{"type":"null"}]}},"type":"object","title":"JobStartRequest"},"JobStartResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"status":{"type":"string","title":"Status"}},"type":"object","required":["job_id","status"],"title":"JobStartResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"Error":{"type":"object","title":"Error","properties":{"detail":{"type":"string","title":"Detail"}},"required":["detail"]}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sk_live_...","description":"Your MakeSplat API key, sent as `Authorization: Bearer sk_live_...`. Create and revoke keys at https://makesplat.com/dashboard/keys."}}},"tags":[{"name":"scans","description":"Create a scan, upload a video, start processing and download the Gaussian splat `.ply`. Every call needs `Authorization: Bearer sk_live_...`."}],"externalDocs":{"description":"MakeSplat API guide","url":"https://makesplat.com/docs"}}