跳到主内容

创建 / 编辑角色卡 · Upsert Character Card

创建一张新角色卡,或编辑自己已有的角色卡(对应 App 内「工作室」的保存操作)。接口为 upsert 语义

  • 不传 id:新建角色卡,响应返回新卡的 cardId
  • id:编辑该角色卡,仅限作者本人,且需满足下方「编辑锁定规则」。

接口地址

POST https://xiangcao.ai/api/upsert-character-card

普通(非流式)接口,走 /api 前缀。

鉴权

需要在请求头携带 API Key:

Authorization: Bearer <YOUR_API_KEY>

缺少或无效的 Token 会返回 401。接口对每个用户有调用频率限制(rate limit)。

编辑锁定规则

为保证已发布内容稳定,已有角色卡满足以下任一条件时将无法再编辑,请求返回 403

条件错误码(响应 error 字段)
不是该角色卡的作者CHARACTER_CARD_STUDIO_EDIT_NOT_OWNER
卡片热度等级达到 1 级(微热)及以上CHARACTER_CARD_STUDIO_EDIT_TIER_BLOCKED
卡片创建时间超过 30 天CHARACTER_CARD_STUDIO_EDIT_EXPIRED

可在编辑前调用预检接口,判断是否还能保存(如决定是否展示「编辑」入口):

POST https://xiangcao.ai/api/get-character-card-studio-editable
Body: { "id": "<cardId>" }
响应: { "editable": true | false }

编辑已有卡的推荐流程

data 为整体覆盖:编辑时服务端会用你提交的 data 完整替换原有 data,漏传的子字段(世界书、备选问候语等)会丢失。因此务必「先读后写」:

  1. list-my-character-cards 分页拉取自己的角色卡(可按 status 过滤),或使用新建时返回的 cardId
  2. 调用 get-character-card(Body { "id": "<cardId>" },仅作者可调)获取完整卡片数据,包括世界书、miniapp 等编辑器字段。
  3. 在返回结果的基础上修改字段,把完整卡片(含 id)回传本接口保存。

顶层字段(statusisAnonymous 等)则是传了才更新,未传的保持原值。

请求体(JSON)

顶层字段

字段类型必填说明
idstring要编辑的角色卡 ID;不传表示新建。
dataobject角色卡核心数据,见下表。编辑时整体覆盖原值
statusstring可见性:public(公开发布,进入广场/搜索/推荐)/ private(归档,仅自己可见)。新建时建议显式传;不传则不会进入任何公开列表。
isAnonymousboolean匿名发布:卡片仍公开,但隐藏作者昵称与头像(App 内该开关为会员专享)。

统计与审核类字段(popularitypopularityTiertrendingScorecardReviewScorecreatedBycreatedAtmoderationStatus 等)由系统维护,请求中传入会被忽略。

data 常用字段

角色卡数据兼容 SillyTavern Character Card V2/V3 规范,并扩展了若干平台字段。只有 nicknameavatarUrl 必填:

字段类型必填说明
nicknamestring角色昵称,对话中角色使用的名字。
avatarUrlstring角色头像 URL(可先用 upload-image 接口上传图片获取)。
namestring作品名称(展示标题),不进入提示词;留空则展示昵称。
descriptionstring角色描述:性格、背景、说话方式等核心设定,是 AI 扮演的主要依据。
personalitystring性格特点摘要,作为描述的补充。
scenariostring场景设定:对话发生的时间、地点与背景。
first_messtring开场白,新对话的第一条消息。
alternate_greetingsstring[]备选问候语,提供不同起始场景。
mes_examplestring对话示例,可用 {{char}} / {{user}} 占位符。
creator_notesstring创作者备注(给使用者的说明),不进入提示词。
appearancestring角色外观描述,用于 AI 生图保持形象一致。
posterUrlstring海报(大尺寸封面)URL,未设置时使用头像。
greetingImageUrlstring随开场白一起展示的图片 URL。
genderstring角色性别:male / female / other,用于分类筛选。
tagsstring[]标签,用于分类与搜索,不进入提示词。
character_versionstring版本号,如 "1.0"
presetOptionsstring[]快捷回复:预设选项按钮,用户点击后作为消息发送。
presetStatusBlockstring初始状态文本,附加到开场白中(建议 emoji + 键值对格式)。
statusBlockConfigobject状态追踪配置(JSON Schema 风格),定义 AI 需动态追踪的属性。
character_bookobject内嵌角色书(世界书),含触发关键词条目。
worldBookRefsobject[]引用的独立世界书,形如 { worldBookId, enabled }最多 5 条
system_promptstring系统提示词(高级)。
post_history_instructionsstring历史后指令(高级)。
creatorstring创作者名。服务端会自动覆盖为你的账号昵称,传入无效。

类型定义(TypeScript)

interface UpsertCharacterCardRequest {
  /** 要编辑的角色卡 ID;不传表示新建 */
  id?: string;
  /** 角色卡核心数据(编辑时整体覆盖) */
  data: CharacterCardData;
  /** 可见性:public 公开 / private 归档 */
  status?: "private" | "public";
  /** 匿名发布:隐藏作者昵称与头像 */
  isAnonymous?: boolean;
}

/** 兼容 SillyTavern V2/V3 的 data 字段 + 平台扩展,仅列常用字段 */
interface CharacterCardData {
  /** 角色昵称(必填) */
  nickname?: string;
  /** 头像 URL(必填) */
  avatarUrl?: string;
  /** 作品名称(展示标题) */
  name?: string;
  description?: string;
  personality?: string;
  scenario?: string;
  first_mes?: string;
  alternate_greetings?: string[];
  mes_example?: string;
  creator_notes?: string;
  appearance?: string;
  posterUrl?: string;
  greetingImageUrl?: string;
  gender?: "male" | "female" | "other";
  tags?: string[];
  character_version?: string;
  presetOptions?: string[];
  presetStatusBlock?: string;
  statusBlockConfig?: Record<string, unknown>;
  character_book?: CharacterBook;
  /** 最多 5 条 */
  worldBookRefs?: { worldBookId: string; enabled: boolean }[];
  system_prompt?: string;
  post_history_instructions?: string;
}

interface CharacterBook {
  name?: string;
  entries: Array<{
    /** 触发关键词 */
    keys: string[];
    /** 触发时注入提示词的内容 */
    content: string;
    enabled: boolean;
    insertion_order: number;
    extensions: Record<string, unknown>;
  }>;
  scan_depth?: number;
  token_budget?: number;
  recursive_scanning?: boolean;
  extensions: Record<string, unknown>;
}

响应(JSON)

新建返回 201,编辑返回 200

字段类型说明
successboolean是否成功。
messagestring结果描述。
cardIdstring角色卡 ID。新建时请保存,后续编辑、发起对话都用它。
interface UpsertCharacterCardResponse {
  success: boolean;
  message: string;
  /** 新建时为新卡 ID;编辑时等于请求的 id */
  cardId: string;
}

公开发布门槛

status: "public" 并非无条件生效。卡片需有头像,且设定总字数(data 序列化后的字数,含世界书)不少于 256 字;不满足时服务端会自动把本次保存降级为 private(归档),响应仍为成功。如需确认最终状态,可用 get-character-card 回读 status

内容规范:不得发布未成年角色、搬运/高度重复的角色卡,也不得在发布后清空或恶意篡改设定。违规卡片会被平台下架或封禁,并可能影响作者等级与相关权益。

示例

新建一张角色卡:

curl -X POST "https://xiangcao.ai/api/upsert-character-card" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "public",
    "data": {
      "nickname": "苏晚",
      "avatarUrl": "https://cdn.example.com/avatars/suwan.png",
      "name": "雨夜侦探苏晚",
      "description": "都市悬疑里的冷面侦探,习惯在雨夜整理案卷……",
      "first_mes": "(她合上案卷,抬眼看你)说吧,这次又是什么案子。",
      "gender": "female",
      "tags": ["悬疑", "都市"]
    }
  }'

响应(201):

{
  "success": true,
  "message": "Character card saved successfully",
  "cardId": "card_abc123"
}

编辑已有卡(先 get-character-card 拉全量,改完整体回传):

curl -X POST "https://xiangcao.ai/api/get-character-card" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{ "id": "card_abc123" }'

# 在返回的完整卡片上修改字段后:
curl -X POST "https://xiangcao.ai/api/upsert-character-card" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "card_abc123",
    "data": { ...完整的 data,含本次修改... }
  }'

响应(200):

{
  "success": true,
  "message": "Character card updated successfully",
  "cardId": "card_abc123"
}

编辑被锁定时(403):

{
  "error": "CHARACTER_CARD_STUDIO_EDIT_TIER_BLOCKED"
}

错误处理

出错时返回相应 HTTP 状态码及 JSON:{ "error": "..." }

状态码说明
400缺少 data、昵称或头像;worldBookRefs 超过 5 条;miniapp 数据非法。
401未携带有效的 Bearer Token,或账号已被封禁。
403编辑被锁定:非作者 / 热度达标 / 创建超 30 天,见上方错误码表。
404要编辑的角色卡不存在。
429触发调用频率限制。
500服务端内部错误(Failed to save character card)。

相关接口

  • 生成角色卡评估:保存后让 AI 评分,达标可自动发布到频道。
  • 获取公开角色卡列表:浏览平台公开卡。
  • get-character-card:拉取自己某张卡的完整数据(编辑前必读)。
  • list-my-character-cards:分页列出自己的全部角色卡。
  • get-character-card-studio-editable:预检某张卡是否还能编辑。