Превращает одно фото в 3D-модель - отдельно для человека (фигура и поза) или для выбранного объекта в кадре. Цена - 4 рубля за изображение.
Общая документация Public API · API-ключ можно создать в настройках аккаунта
SAM 3D восстанавливает объём по одной обычной фотографии и отдаёт готовую 3D-сцену в формате GLB. Нейросеть умеет две разные вещи, и режим выбирается полем sam3_generation_type:
body - 3D-фигура человека: поза и пропорции всех людей в кадре. Подходит для референсов позы, аватаров, заготовок под риггинг и примерки;objects - 3D-модель выбранного предмета из кадра: кресла, игрушки, машины, статуэтки. Предмет находится по короткому названию в prompt или по готовым маскам.Запуск стоит 4 ₽ в любом режиме. Каждый вызов создаёт асинхронную операцию: сначала приходит её id, готовый файл забирается отдельным запросом. Обычно результат готов за 10-70 секунд.
POST /api/v1/operationsAuthorization: Bearer brth_...id и статус queued. Результат забирается по id.Сценарии:
body).body + mask_url).objects + prompt).objects + mask_urls).{
"tool": "sam-3d",
"input": {
"sam3_generation_type": "body",
"image_url": "https://cdn.example.com/person-full-height-1.jpg",
"use_body_mask": false,
"export_meshes": true,
"include_3d_keypoints": true
}
}
tool - slug нейросети, всегда "sam-3d".input - параметры запуска. Поля передаются прямо внутри input, без дополнительной вложенности.body нужны поля фигуры, для objects - prompt и при желании маски.| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
sam3_generation_type | string | Да | Режим: body - 3D-фигура человека, objects - 3D-модель предмета из кадра. |
image_url | string (url) | Да | Ссылка на исходное фото. Одно изображение JPG, JPEG, PNG или WebP. |
use_body_mask | boolean | Нет | Только для body. true - вы передаёте маску человека в mask_url, и модель строит только его. По умолчанию false: модель сама находит всех людей в кадре. |
mask_url | string (url) | Только для body при use_body_mask: true | Ссылка на маску в формате PNG: нужный человек закрашен белым, всё остальное чёрное. Размер маски в пикселях - как у фото. |
export_meshes | boolean | Нет | Только для body. Просит модель подготовить отдельные меши по каждому человеку. В ответ API они не попадают: результат всегда один общий GLB, где каждый человек - отдельный узел сцены. |
include_3d_keypoints | boolean | Нет | Только для body. true - добавить в GLB маркеры ключевых точек тела (по 70 на человека). Удобно для проверки позы и привязки скелета. false - в сцене останутся только фигуры. |
prompt | string | Да, для objects | Только для objects. Короткое название предмета, который нужно вытащить из кадра: chair, fox, armchair. Одно-два слова, лучше по-английски. Если переданы mask_urls, поле всё равно нужно, но предметы берутся из масок. |
mask_urls | string[] (url) | Нет | Только для objects. От 1 до 8 масок, по одной на предмет: предмет белый, фон чёрный, размер как у фото. Форматы JPG, JPEG, PNG или WebP, для масок лучше PNG. |
seed | number | Нет | Только для objects. Целое число для повторяемости: с тем же фото, запросом и seed результат получится таким же. |
detection_threshold | number | Нет | Только для objects. Порог уверенности при поиске предмета по prompt, от 0.1 до 1.0, шаг 0.01. Чем ниже, тем охотнее модель находит предмет, но может захватить лишнее. |
export_textured_glb | boolean | Нет | Только для objects. true - GLB с текстурой, снятой с фото. false - модель без текстуры. |
Поля другого режима можно не передавать: если они есть в запросе, модель их не использует.
Самый частый сценарий: фото человека в полный рост или по пояс. Если в кадре несколько людей, в одну сцену попадут все.
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "sam-3d",
"input": {
"sam3_generation_type": "body",
"image_url": "https://cdn.example.com/person-full-height-1.jpg",
"use_body_mask": false,
"export_meshes": true,
"include_3d_keypoints": true
}
}'
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'sam-3d',
input: {
sam3_generation_type: 'body',
image_url: 'https://cdn.example.com/person-full-height-1.jpg',
use_body_mask: false,
export_meshes: true,
include_3d_keypoints: true,
},
}),
})
const data = await response.json()
console.log(data.id, data.status)
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'sam-3d',
'input': {
'sam3_generation_type': 'body',
'image_url': 'https://cdn.example.com/person-full-height-1.jpg',
'use_body_mask': False,
'export_meshes': True,
'include_3d_keypoints': True,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Если в кадре толпа, а нужна фигура одного человека, закрасьте его белым на чёрной PNG-маске того же размера и включите use_body_mask.
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "sam-3d",
"input": {
"sam3_generation_type": "body",
"image_url": "https://cdn.example.com/group-photo-1.jpg",
"use_body_mask": true,
"mask_url": "https://cdn.example.com/group-photo-1-person-mask.png",
"export_meshes": false,
"include_3d_keypoints": false
}
}'
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'sam-3d',
input: {
sam3_generation_type: 'body',
image_url: 'https://cdn.example.com/group-photo-1.jpg',
use_body_mask: true,
mask_url: 'https://cdn.example.com/group-photo-1-person-mask.png',
export_meshes: false,
include_3d_keypoints: false,
},
}),
})
const data = await response.json()
console.log(data.id, data.status)
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'sam-3d',
'input': {
'sam3_generation_type': 'body',
'image_url': 'https://cdn.example.com/group-photo-1.jpg',
'use_body_mask': True,
'mask_url': 'https://cdn.example.com/group-photo-1-person-mask.png',
'export_meshes': False,
'include_3d_keypoints': False,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Модель сама найдёт предмет по prompt и построит его в 3D. Пишите одно-два слова - название того, что действительно видно на фото.
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "sam-3d",
"input": {
"sam3_generation_type": "objects",
"image_url": "https://cdn.example.com/living-room-1.jpg",
"prompt": "armchair",
"detection_threshold": 0.3,
"seed": 42,
"export_textured_glb": true
}
}'
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'sam-3d',
input: {
sam3_generation_type: 'objects',
image_url: 'https://cdn.example.com/living-room-1.jpg',
prompt: 'armchair',
detection_threshold: 0.3,
seed: 42,
export_textured_glb: true,
},
}),
})
const data = await response.json()
console.log(data.id, data.status)
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'sam-3d',
'input': {
'sam3_generation_type': 'objects',
'image_url': 'https://cdn.example.com/living-room-1.jpg',
'prompt': 'armchair',
'detection_threshold': 0.3,
'seed': 42,
'export_textured_glb': True,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
Когда предмет не находится по названию или нужно несколько конкретных предметов, передайте маски - по одной на предмет. Все предметы окажутся в одной сцене.
curl -X POST https://bratuha.ru/api/v1/operations \
-H "Authorization: Bearer brth_ваш_ключ" \
-H "Content-Type: application/json" \
-d '{
"tool": "sam-3d",
"input": {
"sam3_generation_type": "objects",
"image_url": "https://cdn.example.com/desk-photo-1.jpg",
"prompt": "lamp",
"mask_urls": [
"https://cdn.example.com/desk-photo-1-lamp-mask.png",
"https://cdn.example.com/desk-photo-1-mug-mask.png"
],
"export_textured_glb": true
}
}'
const response = await fetch('https://bratuha.ru/api/v1/operations', {
method: 'POST',
headers: {
Authorization: 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
body: JSON.stringify({
tool: 'sam-3d',
input: {
sam3_generation_type: 'objects',
image_url: 'https://cdn.example.com/desk-photo-1.jpg',
prompt: 'lamp',
mask_urls: [
'https://cdn.example.com/desk-photo-1-lamp-mask.png',
'https://cdn.example.com/desk-photo-1-mug-mask.png',
],
export_textured_glb: true,
},
}),
})
const data = await response.json()
console.log(data.id, data.status)
import requests
response = requests.post(
'https://bratuha.ru/api/v1/operations',
headers={
'Authorization': 'Bearer brth_ваш_ключ',
'Content-Type': 'application/json',
},
json={
'tool': 'sam-3d',
'input': {
'sam3_generation_type': 'objects',
'image_url': 'https://cdn.example.com/desk-photo-1.jpg',
'prompt': 'lamp',
'mask_urls': [
'https://cdn.example.com/desk-photo-1-lamp-mask.png',
'https://cdn.example.com/desk-photo-1-mug-mask.png',
],
'export_textured_glb': True,
},
},
timeout=30,
)
print(response.status_code)
print(response.json())
{
"id": "op_uuid-123",
"status": "queued",
"tool": "sam-3d",
"cost": 4,
"balance_after": 496,
"created_at": "2026-09-30T21:31:26.036498+00:00"
}
{
"id": "op_uuid-123",
"status": "completed",
"tool": "sam-3d",
"cost": 4,
"created_at": "2026-09-30T21:31:26.036498+00:00",
"completed_at": "2026-09-30T21:31:49.648659+00:00",
"result": {
"type": "file",
"files": [
{
"url": "https://storage.bratuha.ru/results/sam-3d/person-full-height-1.glb",
"name": "result"
}
]
},
"error_message": null
}
Если модель не нашла на фото то, что нужно построить, операция завершается статусом failed, result равен null, а причина лежит в error_message:
{
"id": "op_uuid-123",
"status": "failed",
"tool": "sam-3d",
"cost": 4,
"created_at": "2026-09-30T21:31:26.036498+00:00",
"completed_at": "2026-09-30T21:31:33.102114+00:00",
"result": null,
"error_message": "На изображении не обнаружено людей."
}
Для режима objects похожая ошибка звучит так: «Автоматическое выделение объектов не сработало. Попробуйте изменить запрос, добавить ссылки на маски или снизить порог обнаружения.»
Сохраните id из ответа на создание и проверяйте операцию по нему:
GET /api/v1/operations/{id}
curl -H "Authorization: Bearer brth_ваш_ключ" \
https://bratuha.ru/api/v1/operations/op_uuid-123
async function waitForModel(id) {
while (true) {
const res = await fetch(`https://bratuha.ru/api/v1/operations/${id}`, {
headers: { Authorization: 'Bearer brth_ваш_ключ' },
})
const op = await res.json()
if (op.status === 'completed') return op.result.files[0].url
if (op.status === 'failed') throw new Error(op.error_message)
await new Promise((r) => setTimeout(r, 5000))
}
}
Статус одной операции можно запрашивать не чаще раза в секунду, иначе придёт 429 rate_limit_exceeded. Для этой нейросети хватает опроса раз в 5 секунд.
После завершения в result приходит один файл - 3D-сцена в формате GLB:
{
"type": "file",
"files": [
{
"url": "https://storage.bratuha.ru/results/sam-3d/person-full-height-1.glb",
"name": "result"
}
]
}
type - всегда "file".files - массив из одного элемента. url - ссылка на .glb, name - служебное имя "result", расширение берите из ссылки.body в GLB лежат фигуры всех найденных людей: каждый человек - отдельный узел person_00, person_01 и так далее. Фигуры без текстуры, окрашены по вершинам. При include_3d_keypoints: true рядом появляются маркеры суставов keypoint_p00_k00, keypoint_p00_k01... по 70 на человека. Файл на двух людей весит около 2 МБ.objects в GLB лежат найденные предметы, с текстурой при export_textured_glb: true.GLB открывается в Blender, Windows 3D Viewer, онлайн-просмотрщиках и движках вроде Unity и Unreal. Скачайте файл к себе после завершения операции, если он нужен надолго.
Цена фиксированная - 4 ₽ за запуск.
| Что меняется | Влияет на цену |
|---|---|
Режим body или objects | Нет |
| Число людей или предметов в кадре | Нет |
Маски (mask_url, mask_urls) | Нет |
export_meshes, include_3d_keypoints, export_textured_glb | Нет |
Сумма списывается при создании операции и приходит в поле cost, остаток баланса - в balance_after. Если операция завершилась ошибкой, деньги возвращаются на баланс, а cost в ответе остаётся суммой запуска.
POST /api/v1/operations не идемпотентен: каждый запрос создаёт новую операцию и списывает деньги. Если ответ не дошёл из-за обрыва сети, не повторяйте запрос автоматически - сначала проверьте баланс или историю в аккаунте.queued, дальше статус проверяется по id. Фигура человека обычно готова за 10-30 секунд, предмет с текстурой - до минуты с небольшим.http/https. Адреса localhost, loopback и частные IP не принимаются. Ссылка должна открываться без авторизации и cookies, файл - до 128 МБ.400 validation_error и деньги не спишутся. Для mask_url подходит только .png.body работает только с людьми. На фото без человека, на иконках, логотипах, рисунках предметов операция завершится ошибкой «На изображении не обнаружено людей.» Чтобы построить предмет, используйте objects.objects чаще всего ошибаются с prompt. Пишите название предмета, который точно есть в кадре: запрос car на фото кресла не сработает. Короткие английские названия находятся надёжнее: на одном и том же фото fox сработал, а лиса - нет. Длинные описания вроде «здание зелёное» тоже не подходят.detection_threshold пониже (например, 0.2), маску предмета в mask_urls.