{"openapi":"3.1.0","info":{"title":"StableSAM","description":"SAM 3 video segmentation via micropayments. Use StableUpload first, then submit a StableUpload public URL plus declaredFrameCount.","version":"0.1.0","x-guidance":"# StableSAM API\n\nVideo segmentation and object tracking via micropayments. No API keys.\n\nBase URL: `https://stablesam.dev`\n\n## Required Workflow\n\nStableSAM does not accept raw file uploads.\n\n1. Upload the input video to StableUpload.\n2. Compute the video's frame count locally before submission.\n3. Use the StableUpload `publicUrl` as `videoUrl`.\n4. Submit the StableSAM request with `declaredFrameCount`.\n5. Poll the StableSAM job until it completes.\n\n## Important MVP Rules\n\n- `videoUrl` must be a StableUpload public URL.\n- `declaredFrameCount` is required.\n- Requests above `960` frames are rejected.\n- Requests whose StableUpload asset is above `100 MB` are rejected.\n- Price is computed dynamically from `declaredFrameCount`.\n- Segmented output video is silent. StableSAM does not preserve the source audio track.\n\n## Suggested local frame count check\n\nBefore calling StableSAM, inspect the local file with a local tool such as `ffprobe` and compute:\n\n- total frames\n- or `duration * fps`\n\nPrefer exact frame count when available.\n\n## Upload Step\n\nUse StableUpload first:\n\n`POST https://stableupload.dev/api/upload`\n\n```json\n{\n  \"filename\": \"clip.mp4\",\n  \"contentType\": \"video/mp4\",\n  \"tier\": \"100mb\"\n}\n```\n\nThen `PUT` the file to the returned `uploadUrl` and use `publicUrl` in StableSAM.\n\n## Create Job\n\n`POST /api/segment`\n\n```json\n{\n  \"type\": \"sam-3-video-segment\",\n  \"videoUrl\": \"https://f.stableupload.dev/abc123/clip.mp4\",\n  \"declaredFrameCount\": 320,\n  \"prompt\": \"person, skateboard\",\n  \"pointPrompts\": [],\n  \"boxPrompts\": [],\n  \"applyMask\": true,\n  \"videoOutputType\": \"mp4\",\n  \"detectionThreshold\": 0.5\n}\n```\n\n## Point Prompt Example\n\n```json\n{\n  \"type\": \"sam-3-video-segment\",\n  \"videoUrl\": \"https://f.stableupload.dev/abc123/clip.mp4\",\n  \"declaredFrameCount\": 320,\n  \"prompt\": \"\",\n  \"pointPrompts\": [\n    { \"x\": 640, \"y\": 300, \"label\": 1, \"objectId\": 1, \"frameIndex\": 0 },\n    { \"x\": 580, \"y\": 310, \"label\": 0, \"objectId\": 1, \"frameIndex\": 0 }\n  ],\n  \"boxPrompts\": [],\n  \"applyMask\": true,\n  \"videoOutputType\": \"mp4\",\n  \"detectionThreshold\": 0.5\n}\n```\n\n## Box Prompt Example\n\n```json\n{\n  \"type\": \"sam-3-video-segment\",\n  \"videoUrl\": \"https://f.stableupload.dev/abc123/clip.mp4\",\n  \"declaredFrameCount\": 320,\n  \"prompt\": \"\",\n  \"pointPrompts\": [],\n  \"boxPrompts\": [\n    {\n      \"xMin\": 450,\n      \"yMin\": 120,\n      \"xMax\": 760,\n      \"yMax\": 620,\n      \"objectId\": 1,\n      \"frameIndex\": 0\n    }\n  ],\n  \"applyMask\": true,\n  \"videoOutputType\": \"mp4\",\n  \"detectionThreshold\": 0.5\n}\n```\n\n## Poll Job\n\n`GET /api/jobs/{jobId}`\n\nStatuses:\n\n- `pending`\n- `queued`\n- `processing`\n- `complete`\n- `failed`\n\n## Guidance for Agents\n\n- Use StableUpload public URLs only.\n- Compute `declaredFrameCount` locally before sending the request.\n- Keep `objectId` stable across prompts for the same object.\n- Use `frameIndex: 0` unless a later frame is intentionally needed.\n- Use foreground points first and add background points only to reduce mask bleed.\n- Use `videoOutputType: \"mp4\"` unless `webm` is specifically required.\n- If you need audio in the final asset, mux the original audio back in after segmentation. StableSAM outputs silent video.\n","guidance":"# StableSAM API\n\nVideo segmentation and object tracking via micropayments. No API keys.\n\nBase URL: `https://stablesam.dev`\n\n## Required Workflow\n\nStableSAM does not accept raw file uploads.\n\n1. Upload the input video to StableUpload.\n2. Compute the video's frame count locally before submission.\n3. Use the StableUpload `publicUrl` as `videoUrl`.\n4. Submit the StableSAM request with `declaredFrameCount`.\n5. Poll the StableSAM job until it completes.\n\n## Important MVP Rules\n\n- `videoUrl` must be a StableUpload public URL.\n- `declaredFrameCount` is required.\n- Requests above `960` frames are rejected.\n- Requests whose StableUpload asset is above `100 MB` are rejected.\n- Price is computed dynamically from `declaredFrameCount`.\n- Segmented output video is silent. StableSAM does not preserve the source audio track.\n\n## Suggested local frame count check\n\nBefore calling StableSAM, inspect the local file with a local tool such as `ffprobe` and compute:\n\n- total frames\n- or `duration * fps`\n\nPrefer exact frame count when available.\n\n## Upload Step\n\nUse StableUpload first:\n\n`POST https://stableupload.dev/api/upload`\n\n```json\n{\n  \"filename\": \"clip.mp4\",\n  \"contentType\": \"video/mp4\",\n  \"tier\": \"100mb\"\n}\n```\n\nThen `PUT` the file to the returned `uploadUrl` and use `publicUrl` in StableSAM.\n\n## Create Job\n\n`POST /api/segment`\n\n```json\n{\n  \"type\": \"sam-3-video-segment\",\n  \"videoUrl\": \"https://f.stableupload.dev/abc123/clip.mp4\",\n  \"declaredFrameCount\": 320,\n  \"prompt\": \"person, skateboard\",\n  \"pointPrompts\": [],\n  \"boxPrompts\": [],\n  \"applyMask\": true,\n  \"videoOutputType\": \"mp4\",\n  \"detectionThreshold\": 0.5\n}\n```\n\n## Point Prompt Example\n\n```json\n{\n  \"type\": \"sam-3-video-segment\",\n  \"videoUrl\": \"https://f.stableupload.dev/abc123/clip.mp4\",\n  \"declaredFrameCount\": 320,\n  \"prompt\": \"\",\n  \"pointPrompts\": [\n    { \"x\": 640, \"y\": 300, \"label\": 1, \"objectId\": 1, \"frameIndex\": 0 },\n    { \"x\": 580, \"y\": 310, \"label\": 0, \"objectId\": 1, \"frameIndex\": 0 }\n  ],\n  \"boxPrompts\": [],\n  \"applyMask\": true,\n  \"videoOutputType\": \"mp4\",\n  \"detectionThreshold\": 0.5\n}\n```\n\n## Box Prompt Example\n\n```json\n{\n  \"type\": \"sam-3-video-segment\",\n  \"videoUrl\": \"https://f.stableupload.dev/abc123/clip.mp4\",\n  \"declaredFrameCount\": 320,\n  \"prompt\": \"\",\n  \"pointPrompts\": [],\n  \"boxPrompts\": [\n    {\n      \"xMin\": 450,\n      \"yMin\": 120,\n      \"xMax\": 760,\n      \"yMax\": 620,\n      \"objectId\": 1,\n      \"frameIndex\": 0\n    }\n  ],\n  \"applyMask\": true,\n  \"videoOutputType\": \"mp4\",\n  \"detectionThreshold\": 0.5\n}\n```\n\n## Poll Job\n\n`GET /api/jobs/{jobId}`\n\nStatuses:\n\n- `pending`\n- `queued`\n- `processing`\n- `complete`\n- `failed`\n\n## Guidance for Agents\n\n- Use StableUpload public URLs only.\n- Compute `declaredFrameCount` locally before sending the request.\n- Keep `objectId` stable across prompts for the same object.\n- Use `frameIndex: 0` unless a later frame is intentionally needed.\n- Use foreground points first and add background points only to reduce mask bleed.\n- Use `videoOutputType: \"mp4\"` unless `webm` is specifically required.\n- If you need audio in the final asset, mux the original audio back in after segmentation. StableSAM outputs silent video.\n","contact":{"name":"Merit Systems","url":"https://stable-sam.vercel.app"}},"servers":[{"url":"https://stable-sam.vercel.app"}],"tags":[{"name":"Jobs"},{"name":"Segment"}],"paths":{"/api/segment":{"post":{"operationId":"segment","summary":"Create a paid SAM 3 video segmentation job. Requires a StableUpload public URL and declaredFrameCount.","tags":["Segment"],"x-payment-info":{"price":{"mode":"dynamic","currency":"USD","min":"0.03","max":"0.60"},"protocols":[{"x402":{}}]},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","const":"sam-3-video-segment"},"videoUrl":{"type":"string","format":"uri"},"declaredFrameCount":{"type":"integer","minimum":1,"maximum":960},"prompt":{"default":"","type":"string","maxLength":500},"pointPrompts":{"default":[],"maxItems":32,"type":"array","items":{"type":"object","properties":{"x":{"type":"integer","minimum":0,"maximum":9007199254740991},"y":{"type":"integer","minimum":0,"maximum":9007199254740991},"label":{"anyOf":[{"type":"number","const":0},{"type":"number","const":1}]},"objectId":{"type":"integer","minimum":1,"maximum":8},"frameIndex":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["x","y","label"]}},"boxPrompts":{"default":[],"maxItems":16,"type":"array","items":{"type":"object","properties":{"xMin":{"type":"integer","minimum":0,"maximum":9007199254740991},"yMin":{"type":"integer","minimum":0,"maximum":9007199254740991},"xMax":{"type":"integer","minimum":0,"maximum":9007199254740991},"yMax":{"type":"integer","minimum":0,"maximum":9007199254740991},"objectId":{"type":"integer","minimum":1,"maximum":8},"frameIndex":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["xMin","yMin","xMax","yMax"]}},"applyMask":{"default":true,"type":"boolean"},"videoOutputType":{"default":"mp4","type":"string","enum":["mp4","webm"]},"detectionThreshold":{"default":0.5,"type":"number","minimum":0.1,"maximum":1},"clientRequestId":{"type":"string","minLength":1,"maxLength":128}},"required":["type","videoUrl","declaredFrameCount"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"status":{"type":"string","enum":["pending","queued","processing"]},"type":{"type":"string","const":"sam-3-video-segment"},"price":{"type":"string"}},"required":["jobId","status","type","price"],"additionalProperties":false}}}},"402":{"description":"Payment Required"}}}},"/api/jobs":{"get":{"operationId":"jobs","summary":"List StableSAM jobs for the authenticated wallet","tags":["Jobs"],"security":[{"siwx":[]}],"responses":{"200":{"description":"Successful response"},"402":{"description":"Authentication Required"}}}},"/api/jobs/:jobId":{"get":{"operationId":"jobs_status","summary":"Get a StableSAM job status by ID","tags":["Jobs"],"security":[{"siwx":[]}],"responses":{"200":{"description":"Successful response"},"402":{"description":"Authentication Required"}}},"delete":{"operationId":"jobs_delete","summary":"Soft-delete a finished StableSAM job","tags":["Jobs"],"security":[{"siwx":[]}],"responses":{"200":{"description":"Successful response"},"402":{"description":"Authentication Required"}}}}},"components":{"securitySchemes":{"siwx":{"type":"apiKey","in":"header","name":"SIGN-IN-WITH-X"}}}}