户型灯光助手 接入文档 自助开户 /portal 首页

接入文档

你的用户用我们托管的出图页面。你这边只做一件事:判定用户是会员还是非会员, 签发一个会话把用户跳进来。用户在页面上一张一张地出图,每出一张从你的预付余额扣一张的钱。

下文 {{BASE}} 指你拿到的接入域名(默认 https://lightplan.elefeed.com)。收藏此网址即可。

快速开始

  1. 到 自助接入大厅 领沙箱 Key 免费联调;或由我们开通账户,交付 API Key 与初始余额(充值制)。
  2. 你的服务端决定给这个用户多少额度(几张图、几条视频),调 POST /api/v2/sessions 拿到一个跳转 url。
  3. 把用户整页跳转到这个 url —— 上传户型图、出图、下载,全在我们页面完成。

你只需要对接一个接口(创建会话)。出图界面、上传、裁剪、下载都是我们的,你不用搭任何前端。

鉴权

创建会话用 Bearer Token,只在你的服务器后端调用:

Authorization: Bearer lp_live_xxxxxxxxxxxxxxxxxxxx
务必:API Key 是后端密钥,绝不要放进网页/App 前端,也不要拼进跳转链接。前端只会拿到我们签发的短时效会话 token —— 它本身也是一个「持有即可用」的凭证,分发方式见成本与安全。

创建会话

POST/api/v2/sessions

一次签发就是一张限额卡:图几张、视频几条、多久有效。规则只有一条 —— 额度写多少用多少,0 或不传 = 不能;没有「不限」(链接谁拿到谁能用, 不限量等于把你的预付余额挂在网上)。

请求体

字段类型说明
max_images 必填number出图额度,单位张。用户每出一张图扣一张额度、扣一次单价;0 或不传 = 不能出图。
max_videosnumber联动视频额度,单位条(与「张」是两种单位,不折算)。0 或不传 = 不能出片 —— 语义与 max_images 完全一样。
ttl_hoursnumber会话有效期(小时),默认 6。
end_user_idstring你侧的用户标识(透传,用于用量统计/对账)。配合 resume 时,它就是「同一个人」的判据。
resumeboolean同一用户续用:传 true(须同时传 end_user_id)→ 这个用户以前签发过会话,就拿回同一条链接:额度不重置、「我的作品」不清空。详见下方「让同一个用户下次进来还是他自己的那一份」。不传 = 每次一条全新的会话。
旧版参数(仅兼容,新接入别用):早期版本按 tier(member/non_member)+ max_renders(次)签发, 张数 = 次 × 档位倍率(会员 ×4 / 非会员 ×1)、不传 = 不限。老集成不用改,行为原样保留 (含「不限」);但档位已从产品里摘除 —— 会员体系是你的事,我们只卖额度。同时传 max_images 时以它为准。

让同一个用户下次进来还是他自己的那一份(resume)

额度和「我的作品」都跟着会话走,不跟着 end_user_id 走。所以签发方式决定了用户看到什么:

你的用法怎么签发用户看到的
一次性体验(落地页试用、给业主发一条链接看效果)不传 resume,每次一条新会话每条链接各是各的:一张新的额度卡、一个空的「我的作品」。链接过期后,那条链接里的作品用户就看不到了。
你自己的用户体系(用户登录你的系统、从你的入口反复进来用)"resume": true + end_user_id同一个人每次进来都是同一条链接:用过的张数接着算,之前出的图和片都在「我的作品」里。

带 resume 时:

安全上的取舍:续用的链接是按用户长期有效的凭证(每次签发都在给它续期),泄露后的损失上限 = 这个用户的剩余额度 × 单价。所以总额度按人按需给,别图省事给个大数。

示例

总共 20 张、链接 24 小时有效:

curl -X POST {{BASE}}/api/v2/sessions \
  -H "Authorization: Bearer $LP_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "max_images": 20,
    "ttl_hours": 24,
    "end_user_id": "u_8841"
  }'

你的用户 u_8841 每次从你的入口进来(一共给他 60 张、4 条片):{ "max_images": 60, "max_videos": 4, "end_user_id": "u_8841", "resume": true } —— 每次都原样传这一句即可。

单张体验:{ "max_images": 1 }。
再允许出 1 条联动视频:加上 "max_videos": 1(记得图至少给 2 张 —— 一条片要两个已出的场景才串得起来)。

响应 200

{
  "session_token": "sess_xxxxx",
  "url": "{{BASE}}/app?s=sess_xxxxx",   // ← 把用户整页跳到这里
  "max_images": 20,                     // 出图额度(张);旧版「不限」会话此处为 -1
  "max_videos": 0,                      // 联动视频额度(条);不传 = 0 = 不能出片
  "max_scenes": 4,                      // 「加场景」一次最多补几个(账户档,只是操作节流)
  "expires_in": 86400,                  // 链接有效期(秒)= ttl_hours × 3600
  "resumed": false,                     // true = 续用了这个用户以前的会话(token 与上次相同)
  "images_used": 0,                     // 这条会话已交付的张数(续用时接着算)
  "images_remaining": 20,               // 还能出几张(已减去正在出的);旧版「不限」会话为 null
  "videos_used": 0,
  "videos_remaining": 0
}

拿到 url 后跳转即可(window.location = url)。会话 token 随机不可猜,但「不可猜」不等于「可公开分发」 —— 谁拿到这个 url,谁就能在有效期内用它出图(算你账)。务必按用户单独签发(别把一条链接发给多个人、别公开张贴),详见成本与安全。

用户在页面上做什么

  1. 上传户型图,用框选工具裁出一个房间。已有效果图的可以直接传效果图(上传卡上二选一):不再从户型图重建房间,上传的图本身就是底图 —— 房间就是图里那间,风格、吊顶、地面不用再选,出的每张场景图与原图同构图同尺寸。原图不计张数;裁剪层用来框掉 logo、水印和图框(留在图里会被复制进每一张场景图),画面里不要有人。
  2. 选空间/风格,再选一个灯光场景 → 生成。出 1 张图,扣 1 张额度。色温可选(2700K / 3000K / 3500K / 4000K):不选就跟随各场景的默认色温;选了,这件作品之后加的场景、修改、重出也都按它出,只改光的颜色、不改开哪些灯(浪漫场景的彩色氛围光照旧保留)。
  3. 觉得像,就在图下面点「+ 加灯光场景」补更多场景 —— 同一个房间、同一套家具,只换灯光。每补一张同样扣一张。出过的场景也能再选一次再出一张(结果不同):同一场景的几张放在同一个框里左右切换,图名叫 明亮1、明亮2、观影1……用户在框里挑更满意的那张;每出一张同样扣一张。
  4. 觉得房间不像(家具位置、朝向、门窗对不上),点底图框上的「再抽一张」(重出底图):按同一张户型图重新出一版基础图,可以写一句「上一版哪里不像」让模型优先修正;新版和当前版一起放在底图框里左右对比,不会自动替换当前底图。重出一次同样扣 1 张。(它和「加场景」是两件事:加场景只换灯光、房间不变;重出底图换的是房间。)
  5. 图里哪一处不对,点那张图上的「修改」:在图上圈出位置、每处写一句怎么改,模型在这张图的基础上只改那几处、其它保持不变,改好的作为同一场景的新一张追加(改灯光 —— 色温、明暗、哪几盏灯亮 —— 要选「整体调整」,光会照到圈外;写的内容像整体改法时页面会提醒);改一次同样扣 1 张。改的是第一张(基础图)时,之后再加的场景都按改好的图出 —— 想让视频里的房间更准,先把基础图改准。
  6. 底图可以自己选:底图的各个版本(第一张、重出的、修改过的)都在底图框里,当前那版挂着「当前底图」标,它就是「加场景」的出发点。改过基础图之后,改好的那张自动成为底图;重出的那版不自动换 —— 对比后点它的「设为底图」才换。要是换完还是觉得上一版更像,再切回去 —— 换底图不出图、不扣额度,来回切都不花钱。
  7. 有 2 个以上场景后,可以把它们串成一条联动视频(如果你给了视频额度)。
  8. 下载。所有图和片都留在这条链接的「我的作品」里,刷新、换设备(同一条链接)都还在。作品跟着链接走:想让同一个用户下次从你的入口进来还能看到之前的作品,签发时带 resume。
为什么一次只出一张:先花 1 张的钱确认「像不像自己家」,像了再往下补 —— 不像的时候没有浪费掉整组场景的钱。
无需登录、无口令,界面/上传/裁剪/出图/下载/合规标识全是我们的。你只负责决定额度并签发会话。

联动视频(可选)

用户对出好的效果图满意后,可以把这一套场景图串成一条智能灯光/窗帘联动演示片(片长跟着场景数走:3 个场景约 22 秒、4 个场景约 28 秒)——同一个房间、同一套家具,灯光按场景切换。这是给业主看的签单物料,不是另一张图。

建议用法:把视频当成升单动作而不是默认赠送 —— 判定这个业主值得投一条片时,再签发一条带 "max_videos": 1 的会话。成本天花板 = 条数 × 视频单价,与出图额度分开算。

计价方式

两个 SKU 分开算:效果图按张、联动视频按条(逐段)。 单价都按账户约定 —— 这一页(公开)只讲算法,不挂数字; 你的价格带 Key 查 GET /api/v2/account(别人看不到),或直接问对接人。

效果图(按张)

每张一个价,按账户谈定(/api/v2/account 的 price_per_image_cents),与用户在页面上选了哪个出图模型无关 —— 换成更贵的那档也不加价,成本差由我们承担。

页面上开放给用户选的出图模型:读取中…。用户选了哪个模型出图,之后「修改」这张图也用它(改不了),所以页面在选模型时就会提示各模型的修改精度。 每个模型还带一句说明(接口里的 hint:它是什么、什么时候选它),页面选模型时同样显示。 默认那档是我们实测下来最贴户型、性价比最好的;其余保留给「这一张想换个感觉」的场合。

联动视频(按条,逐段计价)

片子从一段首镜(户型图俯冲进屋)开始,它直接落在第 1 个场景上; 之后每换一个场景各一段。所以 段数 = 场景数, 每多一个场景就多一段、多一段的钱。 从效果图出发的作品没有户型图,也就没有首镜:片子直接从第 1 个场景的定格开始,段数 = 场景数 − 1,少的正是最贵的那一段,片长短 5 秒多。 你的逐段单价在 /api/v2/account 的 video_hero_cents(首镜)与 video_segment_cents(其余每段): 整条价 = 首镜 + (场景数 − 1) × 每段,自己就能算任意场景数。 例外只有一处:用户勾了「观影」且这单卖了影音设备时,片中会多插一段电视墙运镜(从全景推到正对挂墙电视的特写、停一拍再回来;推过去的落点由出图模型先出一张电视特写「落幅图」钉住)—— 那一条多一段的钱,外加这一张落幅图的钱(/api/v2/account 的 video_closeup_cents)。

首镜比其余段贵,是因为它换了更强的一档 —— 「一张户型图纸变成实景并推进屋里」 是全片最难的一镜,便宜档在这里会幻觉出不存在的走廊、或者把图纸上的符号直接烧进画面。 其余段是在你已经出好的效果图之间做灯光过渡。

段数在用户点「确认」之前就定了,所以这条片扣多少下单当时就算得准; 金额只在你这边可见(/api/v2/usage 与自助面板), 页面上不会向用户显示任何金额。视频只有这一种收法(逐段计价)—— 没有一口价:成本随场景数线性涨,任何一口价都会在某个段数倒挂,那种账没法长期做。

计费

三句话

为什么出图时余额会先降一截

出图前系统先冻结本次预估金额:balance_cents 立即下降、held_cents 等额上升;每交付一张转为实扣,没用掉的部分终态自动退回。所以轮询 /api/v2/account 看到余额降、held 升是正常的,不是提前扣费;部分失败后余额回升也正常。

对账以 /api/v2/usage 的逐笔明细为准 —— 一张图一行、一条视频一行(视频的 scene 为 video),都含你签发会话时传的 end_user_id、场景、单价、图片地址、北京日期。你的会员体系是你的事:给谁多少张额度完全由你决定(max_images 想传几就传几),我们按总用量结算、按消费月度开票。

成本与安全

跳转 url 是「持有即可用」的出图凭证。token 明文挂在地址栏(/app?s=…),会随转发、浏览器历史、Referer、截图、群里贴链接外泄。任何拿到此链接的人,都能在额度与有效期内出图,全部计入你的账单 —— 我们不做用户 / IP / 设备绑定校验。

你手上的四道闸

闸管什么建议
max_images这条会话能出多少张图按需给,给多少就是多少 —— 泄露时最多损失 max_images × 单价
max_videos能出多少条片(片比图贵两个量级)max_images 管不到它。不传就是 0 条 —— 保持这个默认,只在真要给业主看片时按条签发
ttl_hours链接多久失效设尽量短。按用户单独签发,切勿多人共用或公开张贴同一条链接;用 resume 时同一个用户拿回的是同一条链接,每次签发顺带续期
每日花费上限账户每天最多花多少(按北京自然日)可选、默认不设。担心 Key 泄漏或链接被滥用一天烧光余额就找对接人开;命中返回 402 daily_spend_cap_reached(与余额无关,充值解不开,需上调或等次日 0 点重置)

两个别误解的地方

账户级默认限 8 单在途、60 次/分:超出分别返回 429 concurrency_limit / rate_limited,退避后重试即可;压量场景需要更高额度请联系对接人调整。

账户 / 用量(对账)

金额字段单位均为「分」(1 元 = 100 分) —— 对账时除以 100。

GET/api/v2/account
{ "balance_cents": 131110,          // 余额
  "held_cents": 0,                  // 出图中冻结(交付后转实扣,没用掉的退回)
  "price_per_image_cents": 200,     // 每张图单价(与所用模型无关)
  "provider": "gptimage",           // 你账户默认的出图模型(2026-09-10 起默认 GPT Image 2.5 正式版;gptimage_flash = 2.5 Flash 档)
  "video_price_from_cents": 2340,   // 最便宜那条片(2 个场景 = 3 段)多少钱
  "video_hero_cents": 1040,         // 你的首镜价(固定 1 段;按账户,示例数字)
  "video_segment_cents": 650,       // 每个场景 1 段
  "video_per_extra_scene_cents": 650, // 每多勾一个场景多收多少
  "video_markup_pct": 30,           // 逐段计价的加成率(视频只有这一种收法)
  "spent_today_cents": 19090,       // 今日已花(北京日)
  "spent_today_video_cents": 10890, // 其中视频花了多少
  "daily_spend_cap_cents": 0,       // 每日花费上限;0 = 未设
  "max_scenes_per_render": 4,       // 「加场景」一次最多补几张
  "status": "active", "sandbox": false, "timezone": "Asia/Shanghai" }
对账时把两个 SKU 分开算。图按张、视频按条,单价口径完全不同 —— 拿 spent_today_cents 去除以图单价是对不上的,先减掉 spent_today_video_cents。逐笔明细见下面的 /api/v2/usage(视频那行的 scene 是 video)。
GET/api/v2/usage?from=2026-06-01&to=2026-06-30&end_user_id=&cursor=&limit=1000

按北京时区拉取已交付明细(一张图一行、一条视频一行,视频的 scene 为 video),用于你侧对账。每行的 end_user_id 就是你签发这条会话时传的那个,图和视频都带 —— 按人汇总消耗只看这一列;加 end_user_id= 参数可只拉某一个用户。next_cursor 非空时继续翻页。

{ "events": [ {"render_id":"..","end_user_id":"u_8841","scene":"明亮","unit_price_cents":<你的单价>,
    "image_url":"https://..","ts":1781990000,"beijing_date":"2026-06-20"} ],
  "next_cursor": null, "timezone": "Asia/Shanghai" }

把这两个接口接进你自己的后台,你和财务即可随时核对用量与账单。

回调 Webhook(可选)

想在出图状态变化时收到通知(比如更新你侧的用量看板),可以登记一个回调 URL(必须 https、公网可达)。状态共五种:base_ready / done / failed / cancelled / expired。

别把「收到回调」当「出图完成」 —— 每单都会先推一次 base_ready(此时 images 已含第一张图),完成以 status=done/failed 为准。跳转页面这条路的典型序列就是 base_ready → done 两连发;cancelled / expired 极少出现。对未列出的 status 请宽容忽略、照常回 2xx。
X-LightPlan-Signature: <hex>   X-LightPlan-Timestamp: 1781990000   X-LightPlan-Event: evt_xxx
{ "render_id":"..","account_id":"acct_..","status":"done",
  "images":[{"scene":"明亮","url":"https://.."}], "error":"", "created_ts":1781990000 }

验签:HMAC-SHA256(secret, "{timestamp}.{原始请求体}"),并拒绝早于 5 分钟的重放(每次投递——含重试——都按发送时刻现签,放心按 5 分钟卡)。X-LightPlan-Event 是事件唯一 ID —— 重试会重复投同一事件,按这个头去重。

投递语义:我们不跟随重定向,3xx / 4xx 响应(408、429 除外)视为你侧配置错误、该事件立即作废不再重试 —— 请登记最终 URL 并直接返回 2xx;5xx / 超时会退避重试,最多 8 次、约 42 分钟内打完。回调是尽力投递,以 /api/v2/usage 为对账真相源。回调体内嵌的图片 URL 是长期有效的直链,请按敏感数据处理。

错误码

错误统一返回 {"error":"<机器可读码>"} + HTTP 状态:

HTTPerror含义
400resume_needs_end_user_id传了 resume: true 却没传 end_user_id —— 没有「是谁」就谈不上「同一个人」
400invalid_tier传了旧版参数 tier 但值不是 member / non_member(新接入不传 tier,直接给 max_images)
401invalid_api_key / invalid_sessionKey 无效 / 会话无效或过期
402insufficient_balance余额不足 → 充值
402daily_spend_cap_reached触及账户每日花费上限(与余额无关,充值无效)→ 联系对接人上调或等次日北京时间 0 点重置
403account_closed账户已关停 —— 你调 POST /api/v2/sessions 收到的 403 是这个码
403account_suspended账户被暂停;此时 /sessions 仍正常返回 200,该码只在用户随后于我们页面出图时触发。请以 GET /api/v2/account 的 status 判断账户健康度
413(中文提示文案)请求体过大(超约 24MB 在读取前即拦)—— 该响应的 error 是人话提示而非机器码,压缩图片后重试
422image_rejected户型图不合格:太暗 / 太小 / 无法识别 / 文件过大(>12MB) / 分辨率过高(>8000 万像素,常见于 CAD 高分辨率导出) / base64 数据损坏。扣费前就拦
429session_render_limit / session_video_limit / rate_limited / concurrency_limit这条链接的剩余额度不够这一批(图 / 视频)—— 少要几张就能过,额度真用完了也是这个码;请求过快(默认 60 次/分)/ 在途任务达并发上限(默认 8 单)—— 后两者退避后重试

FAQ

会员/非会员怎么区分?

我们不区分,也不介入你的会员体系 —— 你卖给用户什么档位是你的事,对我们只体现为一个数:这条会话给几张(max_images)、给不给视频(max_videos)。想给 VIP 更多,就把数写大。

一个会话能出多少图?

max_images 张,写多少就是多少;每交付一张扣一张。0 或不传 = 不能出图 —— 没有「不限」。

怎么先联调不花钱?

到 自助接入大厅一键领沙箱 Key(免费、秒发):返回占位图、¥0 完全免费不计费,流程与生产一致,联调通过后换生产 Key。

用户上传的图有什么要求?

单个空间的局部图(裁好的一个房间),白底清晰、短边 ≥ 600px;文件 ≤ 12MB、分辨率 ≤ 8000 万像素。我们页面带框选工具帮用户从整套图里裁出一个房间。
常见坑:CAD 直接导出的超高分辨率线稿(文件不大但上亿像素)会被按「分辨率过高」拒收 —— 导出普通分辨率即可,不是图不够清晰,别反向去导更大的图。

出的图带标识吗?

按国标要求,所有 AI 生成图都写入隐式元数据标识;自助开户转正式的账户,出图默认还带右下角「AI生成」可见角标。签约合作的商户可约定关闭可见角标(显式标识责任随合同划转)—— 需要请联系对接人。

自助开户(/portal)遇到的错误码怎么查?

signup_* 系列不在上表(上表只覆盖 Bearer 接口),开户页面上有对应的人话提示。