接口文档

Mod 客栈前台与创作者工作台使用的公开接口参考。

认证 / 会话

登录走 Glosc AI SSO,本站只签发并校验一枚 HttpOnly 会话 Cookie。

GET /api/v1/auth/session - 读取当前会话;401 是正常的“未登录”结果,不是错误

认证: public

响应: User { id, subject, name, nickname, email, phone, avatar, display_name, avatar_url, status, group_id, group_level, permissions[], created_at, updated_at, last_login_at }

GET /api/v1/auth/sso/login - 发起 SSO 登录(整页跳转,不是 fetch 调用)

认证: public

查询参数: redirect_to (string): 登录成功后跳回的站内路径

GET /api/v1/auth/sso/callback - SSO 回调地址,浏览器跳转到达,前端代码不直接调用

认证: public

POST /api/v1/auth/logout - 清本站会话 Cookie;不会吊销已签发的 SSO 令牌

认证: public

响应: { sso_logout_url }

账户资料 / 实名认证

GET /api/v1/profile - 读取本人可编辑资料

认证: user

响应: { user_id, display_name, avatar_url, sso_name, sso_avatar, effective_name, effective_avatar, updated_at }

PATCH /api/v1/profile - 更新昵称 / 头像;省略字段=不改

认证: user

请求体: display_name (string): 留空字符串 '' 会清空并回退到 SSO 昵称; avatar_file_id (number); clear_avatar (boolean)

GET /api/v1/identity-verification - 查询本人实名认证状态

认证: user

响应: { status: 'none'|'pending'|'verified'|'failed', id_number_masked? }

POST /api/v1/identity-verification - 提交实名认证,返回支付宝认证二维码链接(前端轮询 GET 直到 verified/failed)

认证: user

请求体: name (string) [必填]; id_number (string) [必填]

响应: { certify_url }

钱包与支付

入账判据只有一个:用签名接口回查支付中心,状态是 paid。浏览器跳回来不算数。

GET /api/v1/wallet - 读取余额与当前充值可用方式

认证: user

响应: { balance: { available, hold, pending, withdrawable }, topup_withdrawable, sandbox_topup, payment_topup }

GET /api/v1/wallet/transactions - 流水分页

认证: user

查询参数: limit (number); offset (number)

响应: Page<{ id, transaction_id, bucket, amount, kind, reference, memo, created_at }>

POST /api/v1/wallet/topups - 沙箱直记账充值;只在 sandbox_topup=true 时可用,不经真实支付渠道

认证: user

请求头: Idempotency-Key (string) [必填]

请求体: amount (number) [必填]

响应: { balance }

POST /api/v1/wallet/topups/orders - 创建真实充值订单(微信 / 支付宝);hosted 模式返回 checkout_url,native_qr 模式返回 qr_code_url

认证: user

请求头: Idempotency-Key (string) [必填]

请求体: amount (number) [必填]; channel ('wechat' | 'alipay') [必填]

响应: PaymentOrder { id, app_order_no, payment_order_no, amount_fen, credit_amount, channel, status, qr_code_url?, checkout_url? }

说明: 两个模式互斥:一行只填一个凭证字段,前端据此分流渲染方式,不传模式标志

GET /api/v1/wallet/topups/orders/{id} - 轮询订单状态(≥2 秒一次),入账后 balance 同步返回

认证: user

响应: { order, balance, payable }

说明: {id} 必须是订单的数字 id(下单响应里的 id),不能传字符串 payment_order_no —— 回查接口对字符串返回 400 invalid_id

GET /api/v1/wallet/topups/orders - 充值订单历史

认证: user

查询参数: limit (number); offset (number)

GET /api/v1/payments/currency - 站内货币显示名(如“银两”),全站格式化金额时使用

认证: public

响应: { currency_name }

委托

分阶段(milestones)是当前默认路径;旧的单次交付端点仍在,只服务历史数据。

GET /api/v1/commissions - 委托列表

认证: user

查询参数: scope ('open' | 'mine' | 'assigned'): 默认 open; status (string); limit (number); offset (number)

GET /api/v1/commissions/{id} - 委托详情

认证: user

响应: CommissionDetail { commission, deliveries[], events[], conversation_id, milestones?[], protocol?, milestone_events?[] }

POST /api/v1/commissions - 发布委托

认证: user

请求体: title (string) [必填]; description (string) [必填]; visibility ('public' | 'exclusive') [必填]; target_creator_ids (number[]): 1-10 个,仅 exclusive 时用; reward (number) [必填]: 最小单位; duration_days (number); milestones ({ title, acceptance, ratio_bps }[]) [必填]: 2-10 条,ratio_bps 之和必须等于 10000; rights ({ ...6 个可授权项枚举字段 }) [必填]; inquiry_id (number): 从询价会话转化为委托时携带

POST /api/v1/commissions/{id}/accept - 承接委托(定向邀请下,谁先承接谁做,其余邀请自动置为已拒绝)

认证: user

POST /api/v1/commissions/{id}/decline - 拒绝邀请;非受邀者一律 404(不是 403),避免探测邀请名单

认证: user

POST /api/v1/commissions/{id}/milestones/submit - 作者提交本阶段交付

认证: user

请求体: note (string); download_url (string); file_id (number)

响应: { milestone, delivery }

POST /api/v1/commissions/{id}/milestones/approve - 委托人确认本阶段;末阶段确认即结算全款

认证: user

响应: { commission, milestone }

POST /api/v1/commissions/{id}/milestones/changes - 委托人对本阶段要求修改

认证: user

请求体: reason (string) [必填]

POST /api/v1/commissions/{id}/deliveries - (旧版)单次交付,非分阶段委托使用

认证: user

请求体: note (string); download_url (string); file_id (number)

GET /api/v1/commissions/{id}/deliveries/{delivery_id}/download - 交付物下载;点击时才取短时签名 URL

认证: user

响应: { url }

POST /api/v1/commissions/{id}/changes - (旧版)要求修改

认证: user

请求体: reason (string) [必填]

POST /api/v1/commissions/{id}/complete - 验收结算;终局动作,不可撤销

认证: user

POST /api/v1/commissions/{id}/cancel - 取消委托,赏金退回;同时清空所有未决邀请

认证: user

请求体: reason (string)

POST /api/v1/commissions/{id}/disputes - 提交争议(委托人或作者均可)

认证: user

请求体: reason (string) [必填]: 10-2000 字符

GET /api/v1/commissions/rights-pricing - 可授权项定价表,发布表单实时计价用

认证: public

响应: { pricing: { ...6 个基点字段 } }

GET /api/v1/commissions/stage-templates - 公开的分阶段模板列表,发布表单“套用模板”下拉用

认证: public

响应: StageTemplate[]

会话消息

委托内的私聊,随委托自动建立会话;轮询获取新消息,不是实时推送。

GET /api/v1/conversations - 会话列表,含未读数

认证: user

查询参数: limit (number); offset (number)

响应: Page<ConversationSummary>

GET /api/v1/conversations/{id}/messages - 拉取消息;after_id 用于增量轮询

认证: user

查询参数: after_id (number); limit (number); offset (number)

POST /api/v1/conversations/{id}/messages - 发消息

认证: user

请求体: body (string); attachment_file_id (number)

说明: body 与图片二选一或都带

POST /api/v1/conversations/{id}/read - 推进已读游标

认证: user

请求体: message_id (number): 省略=标记全部已读

询价(联系作者)

作品详情页“联系作者”先走询价私聊,谈妥后可转化为正式委托(发布委托时携带 inquiry_id)。

GET /api/v1/inquiries - 询价列表

认证: user

查询参数: role ('player' | 'creator'): 默认 player; limit (number); offset (number)

POST /api/v1/inquiries - 发起询价

认证: user

请求体: creator_id (number) [必填]; work_id (number); subject (string); body (string) [必填]

GET /api/v1/inquiries/{id} - 询价详情

认证: user

GET /api/v1/inquiries/{id}/messages - 拉取询价消息

认证: user

查询参数: after_id (number)

POST /api/v1/inquiries/{id}/messages - 发送询价消息

认证: user

请求体: body (string); attachment_file_id (number)

POST /api/v1/inquiries/{id}/read - 标记已读

认证: user

POST /api/v1/inquiries/{id}/close - 关闭询价

认证: user

说明: 状态机:pending(玩家发起,创作者未回,玩家被锁)→ open(双方可说话)→ closed

通知

GET /api/v1/notifications - 通知列表

认证: user

查询参数: unread (boolean); limit (number); offset (number)

GET /api/v1/notifications/unread - 导航栏角标用的未读计数(通知与消息分别计数)

认证: user

响应: { notifications, messages }

POST /api/v1/notifications/{id}/read - 标记单条已读

认证: user

POST /api/v1/notifications/read - 全部标记已读

认证: user

响应: { updated }

SEO 元信息与主域名

公开元信息始终按匿名访客投影生成;主域名只用于 canonical、分享信息、结构化数据和 sitemap。

GET /api/v1/seo/meta - 读取受支持站内路径的统一 SEO 元信息

认证: public

查询参数: path (string) [必填]: 站内绝对路径(可带受支持的查询参数);不接受完整 URL 或任意外部地址

响应: PageSEO { title, description, canonical, robots, image?, type, json_ld[] }

说明: 响应不会因 Cookie 或登录态扩大内容可见范围;不存在或匿名不可见的页面返回 404

说明: 动态元信息使用 Cache-Control: no-store

GET /api/v1/admin/seo/settings - 读取 canonical 主域名配置

认证: user

响应: { site_url }

说明: 需要 seo_settings.read 权限

说明: 仅在配置行不存在时返回默认值 https://www.glossmod.com

PUT /api/v1/admin/seo/settings - 校验并保存 canonical 主域名,保存后立即生效

认证: user

请求体: site_url (string) [必填]: 纯域名或 HTTPS 根地址;不允许用户信息、页面路径、查询参数或锚点

响应: { site_url }

说明: 需要 seo_settings.write 权限

说明: 响应返回规范化后的 HTTPS origin;配置修改与审计记录在同一事务中提交

发现层:作品广场 / 标签 / 作者名录

一条 /api/v1/works 路由靠 scope 区分公开广场、我的货架、动态与收藏;未知 scope 返回 422,不回落到广场。

GET /api/v1/works - 作品列表;scope 决定这是公开广场还是登录后的私有列表

认证: optional

查询参数: q (string); tag (string); sort ('latest' | 'updated' | 'oldest'): 默认 latest(按发布时间); creator_id (number); limit (number); offset (number); scope ('mine' | 'following' | 'favorites'): 省略=公开广场(游客可访问);三个取值都需要登录,未知值返回 422 invalid_scope

说明: 封面、标题、简介不受可见性门控;图库每张图、下载每个文件各自有 visibility 门控(登录态影响返回内容,故 auth=optional)

GET /api/v1/works/{id} - 作品详情

认证: optional

响应: WorkDetail { work: { ..., description(已按查看者裁剪隐藏段落), tags?, gallery?: GalleryImage[], files?: WorkFile[] } }

说明: 没有整作品级别的 entitlement 了:gallery 与 files 里每一项各自带 visibility/min_tip_amount/entitlement,同一作品下有的图能看、有的图看不了是正常情况

说明: 正文里用 ```gate:followers``` / ```gate:tippers:5``` 围栏标记的段落,未解锁时服务端已经把原文替换成占位提示,前端拿到的 description 就是裁剪后的结果

GET /api/v1/works/{id}/files/{fileID}/download - 作品当前文件下载;按该项目的关注或购买权益判定,不满足返回 403,文件不属于该作品返回 404

认证: optional

响应: { url }

POST /api/v1/works/{id}/items/purchase - 单项购买;确认该项目当前版本与价格后扣款,打赏不产生此权益

认证: user

请求体: item_type ('file' | 'gallery' | 'gate') [必填]; item_key (string) [必填]: 文件/图库条目 ID,或正文稳定 gate ID;不是上传文件 ID; expected_amount (number) [必填]: 界面确认的价格,最小货币单位;服务端重新定价; work_version (number) [必填]: 界面确认的作品版本; idempotency_key (string) [必填]: 8-64 字符;服务端另以规范项目身份保证只扣一次

响应: PurchaseReceipt { id, work_id, item_type, item_key, amount, work_version, created_at }

说明: 价格或版本变化返回 409,需要重新展示并由用户确认,不能自动重试扣款

说明: 重复购买返回同一回执;作者停止销售不删除已购交付快照

GET /api/v1/works/{id}/purchases - 本人已购版本及授权交付;不依赖作品仍在销售

认证: user

响应: PurchasedContent[] { id, work_id, item_type, item_key, amount, work_version, created_at, name, body?, url?, unavailable_reason? }

说明: 签名下载 URL 短期有效,下载前重新获取

说明: 平台撤回时保留回执但不继续交付;历史无快照订单不回填内容

GET /api/v1/tags - 标签列表(含每个标签下的作品数)

认证: public

响应: Tag[]

GET /api/v1/creators - 作者名录;也是“按昵称选作者”的唯一数据源(发布定向委托、从询价预填卡片都用它)

认证: optional

查询参数: q (string); scope ('following'): 需要登录,用于“我关注的作者”; user_id (number): 按单个作者取卡片信息; limit (number); offset (number)

响应: Page<{ user_id, display_name, avatar_url, level, works_count, follower_count, slug?, headline? }>

说明: 排序固定为等级(经验)从高到低,不可指定排序

作者主页

公开读接口对游客开放;编辑接口只操作草稿,发布前对外不可见。

GET /api/v1/homepages/{slug} - 主页详情;{slug} 可以是 slug 字符串或数字 user_id

认证: public

响应: HomepagePage { homepage, blocks[], creator_name, creator_avatar, creator_level?, owner, default?, follower_count, following }

说明: 已审核作者未发布主页时返回一个 default:true 的默认主页(身份 + 作品墙),不是 404

GET /api/v1/homepages/{slug}/works - 该作者已发布作品墙分页

认证: public

查询参数: q (string); limit (number); offset (number)

GET /api/v1/creator/homepage - 读取本人主页草稿;首次访问会自动建行

认证: user

PATCH /api/v1/creator/homepage - 更新主页基础信息

认证: user

请求体: slug (string): 30 天只能改一次,不做旧链接重定向; headline (string); accent (string); banner_file_id (number); clear_banner (boolean)

PUT /api/v1/creator/homepage/blocks - 整套替换区块(text / gallery / works / links),最多 20 块

认证: user

请求体: blocks (Block[]) [必填]

POST /api/v1/creator/homepage/publish - 把当前草稿整套发布为公开版本

认证: user

GET /api/v1/creator/homepage/preview - 按公开页同样结构渲染草稿,供编辑器预览

认证: user

关注 / 点赞 / 收藏 / 打赏 / 评论

POST /api/v1/creators/{creator_id}/follow - 关注作者

认证: user

响应: { following: boolean }

DELETE /api/v1/creators/{creator_id}/follow - 取消关注

认证: user

GET /api/v1/creators/{creator_id}/follow - 查询本人是否已关注

认证: user

POST /api/v1/works/{id}/like - 点赞作品

认证: user

响应: { liked, count }

DELETE /api/v1/works/{id}/like - 取消点赞

认证: user

GET /api/v1/works/{id}/like - 查询点赞数与本人是否点赞;游客得 liked:false

认证: optional

POST /api/v1/works/{id}/favorite - 收藏作品(私有书签,三个操作都需要登录)

认证: user

响应: { favorited, count }

DELETE /api/v1/works/{id}/favorite - 取消收藏

认证: user

GET /api/v1/works/{id}/favorite - 查询本人是否已收藏

认证: user

POST /api/v1/works/{id}/tip - 独立打赏作品;不解锁文件、图片或正文,不产生购买权益

认证: user

请求体: amount (number) [必填]: 最小单位,≥100; idempotency_key (string) [必填]

响应: { total, idempotent? }

GET /api/v1/works/{id}/tip/total - 本作品累计打赏金额

认证: user

响应: number

GET /api/v1/works/{id}/comments - 评论列表(树形,含 replies)

认证: public

响应: Comment[]

POST /api/v1/works/{id}/comments - 发表评论 / 回复

认证: user

请求体: body (string) [必填]: ≤2000 字符; parent_id (number): 0 或省略=顶层评论

DELETE /api/v1/comments/{comment_id} - 删除评论;仅评论作者本人 / 作品创作者 / 有 comments.moderate 权限者可删,否则 404

认证: user

举证与纠纷

面向委托参与方(委托人 / 作者)本人,不是运营审核视角。

POST /api/v1/commissions/{id}/evidence-requests - 参与方申请开放举证凭证

认证: user

请求体: purpose (string) [必填]: 2-200 字符; reason (string) [必填]: 10-2000 字符

GET /api/v1/commissions/{id}/evidence-requests - 本委托的举证申请列表(参与方或审核员可见)

认证: user

响应: { requests: EvidenceRequest[] }

GET /api/v1/evidence-requests/{id}/credential - 举证凭证详情;申请人本人或审核员可读,每次访问服务端会记审计日志

认证: user

响应: EvidenceCredential { client: PartyIdentity, creator: PartyIdentity, performance, ... }

创作者申请与等级

POST /api/v1/creator/applications - 提交创作者申请

认证: user

请求体: display_name (string) [必填]; portfolio_links (string[]): ≤5 条; statement (string) [必填]; contact_email / contact_phone / contact_qq / contact_wechat (string): 至少填一项

GET /api/v1/creator/applications/me - 查询本人申请状态;404 表示从未申请过

认证: user

GET /api/v1/creator/profile - 查询本人的创作者资料;404 表示尚不是创作者

认证: user

响应: CreatorProfile { level, experience, fee_basis_points, fee_override, ... }

GET /api/v1/creator/tiers - 等级 / 费率表,公开只读,用于展示等级说明

认证: public

响应: { tiers: CreatorTier[] }

创作者工作台:作品管理

/creator/works 下的编辑操作。发布路径是创作者自行 publish,当前不经运营审核。

POST /api/v1/creator/works - 创建作品(草稿)

认证: user

请求体: title (string) [必填]; summary (string); description (string): Markdown 正文;可用 ```gate:followers``` / ```gate:tippers:5``` 围栏标记段落为隐藏内容; cover_file_id (number); clear_cover (boolean); files ({ file_id, name?, description?, visibility?: 'public'|'followers'|'tippers', min_tip_amount? }[]): 没有整作品级别的 visibility/min_tip_amount 了,每个文件各自设置(省略 visibility 默认 public); tags (string[]): ≤5 个,每个 ≤20 字; status (string)

PATCH /api/v1/creator/works/{id} - 更新作品

认证: user

请求体: (同 create): 字段省略=不改;tags/files 传 [] 表示清空

PUT /api/v1/creator/works/{id}/gallery - 整套替换图库,最多 12 张,每张图各自设置 visibility/min_tip_amount

认证: user

请求体: images (GalleryImageInput[]) [必填]

POST /api/v1/creator/works/{id}/publish - 发布作品(草稿或已下架 → 已发布),无需审核

认证: user

POST /api/v1/creator/works/{id}/hide - 下架已发布的作品,创作者本人可逆的操作

认证: user

文件上传

两步式:先建行拿 id,再把裸文件 PUT 给 content 端点;不支持浏览器直传对象存储。

POST /api/v1/uploads - 第一步:登记文件元信息,建一行 pending 记录

认证: user

请求体: original_name (string) [必填]; content_type (string) [必填]; size_bytes (number) [必填]

响应: StoredFile { id, status: 'pending', ... }

PUT /api/v1/uploads/{id}/content - 第二步:把裸文件作为请求体上传(不是 JSON),必须带 Content-Length

认证: user

响应: StoredFile { status: 'ready', ... }

GET /api/v1/uploads/{id}/public-url - 取该文件的公开直链,用于作品 Markdown 正文内嵌图片;未配置公共域名时返回 422

认证: user

响应: { url }