Script 资源与端点

Script 是前端通过 HTTP 调用的声明式后端端点(概念与顶层结构在 Script 概述 中介绍)。本页介绍 Script 资源的 sys 结构与正文属性、编写和执行 Script 的 HTTP 端点规范,以及作为执行记录的 ScriptLog。

创建和管理 Script 的工作(列表、查询、创建、修改、删除)在 CMA(https://cma.weegloo.com/v1)中进行。执行由专用 Script 主机(https://script.weegloo.com/v1)的执行路径负责,这一条执行路径同时接受 Weegloo User 令牌与已注册产品的会员(ServiceUser)令牌。ACMA 中没有 Script API,只读的交付 API(CDA、ACDA)中也没有。

Script 是带有 version 的资源,也是受各套餐数量限制的计费资源。不过与 Content 或 Media 不同,它不具有发布状态。 sys 中没有 status 或 publish 之类的发布相关属性,每次变更只会使 version 递增。由于没有发布、取消发布的概念,删除时也无需取消发布即可直接进行。

资源结构

以下是 Script "t6-http" 的单个查询响应。除 sys(系统属性)外,还具有 name、definition,以及开闭调用路径的 directCallEnabled、anonymousCallEnabled 作为正文属性。

{
  "sys": {
    "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK",
    "type": "Script",
    "space": { "sys": { "id": "6jSUUAWT", "type": "Refer", "targetType": "Space" } },
    "createdBy": { "sys": { "id": "3p4tcFbQYJNvYTBJf2rYKr42xegQLJ", "type": "Refer", "targetType": "User" } },
    "createdAt": "2026-07-15T12:35:47.575Z",
    "updatedBy": { "sys": { "id": "3p4tcFbQYJNvYTBJf2rYKr42xegQLJ", "type": "Refer", "targetType": "User" } },
    "updatedAt": "2026-07-15T12:35:47.575Z",
    "version": 1
  },
  "name": "t6-http",
  "directCallEnabled": true,
  "anonymousCallEnabled": false,
  "definition": {
    "method": "Post",
    "statements": [
      {
        "name": "resp",
        "method": "POST",
        "url": "https://postman-echo.com/post",
        "headers": [ { "key": "Content-Type", "value": "application/json" } ],
        "body": { "prompt": "{ /payload/prompt }" },
        "timeoutMs": 10000,
        "retry": 0,
        "type": "Http"
      },
      {
        "value": { "status": "{ /resp/status }", "prompt": "{ /resp/body/json/prompt }" },
        "isError": false,
        "statusCode": 200,
        "type": "Return"
      }
    ]
  }
}

主要键:

  • sys.id:Script 的唯一标识符。用于单个查询、修改、删除、执行路径中的 {scriptId}。
  • name:Script 的名称(1~64 个字符)。用于界面列表和管理识别。
  • definition:声明此 Script 做什么的 ScriptDefinition。由调用方法(method)、Statement(statements)数组、可选的 payload 模式(payloadSchema)和可选的机密值列表(secrets)构成。详细结构见下方的定义与名称以及 Script 概述的顶层结构。
  • directCallEnabled:此 Script 是否可以通过 /execute 直接调用(布尔值,省略时为 true)。为 false 时直接调用会被拒绝。执行此 Script 的其他路径仍然保持原样。Webhook 的关联动作(script)与 Scheduler 不经过这个端点,因此照常执行。
  • anonymousCallEnabled:此 Script 是否可以不经认证通过 /execute/anonymous 调用(布尔值,省略时为 false)。开启后,无法携带令牌的第三方也能通过那条路径执行此 Script,而执行是以作者身份进行的。条件与保存规则在下面的匿名调用中介绍。

请注意 sys 中没有 status、publish、archive。Script 不是发布到交付路径的资源,而是在管理 API 中编写和执行的资源。

系统属性 (sys)

所有 Script 都在 sys 对象中包含通用的系统属性。space、createdBy、updatedBy 以 Refer 形态({ "sys": { "id", "type": "Refer", "targetType" } })呈现。

属性类型说明
idstring资源唯一标识符。
typestring资源种类。Script 始终为 "Script"。
spaceRefer<Space>此 Script 所属的 Space。
createdByRefer<User>创建的用户。
createdAtstring (date-time)创建时间。
updatedByRefer<User>最后修改的用户。
updatedAtstring (date-time)最后修改时间。
versioninteger (≥1)资源版本。每次创建、修改递增 1。

Content、Content Type、Media 的 sys 中的 status(发布状态)和 publish(发布历史),Script 并不具有。 因为 Script 不会被发布。也没有 archive 属性。因此 Script 的 version 不涉及发布,纯粹随创建、修改的次数递增。

定义与名称 (name, definition)

Script 的正文属性有 name、definition、directCallEnabled、anonymousCallEnabled 四个。

属性必填说明
name必填Script 的名称。1~64 个字符。
definition必填ScriptDefinition。由下表的键构成。
directCallEnabled选填此 Script 是否可以通过 /execute 直接调用。布尔值,省略时为 true。为 false 时直接调用会被拒绝。Webhook 的关联动作(script)与 Scheduler 不经过这个端点,因此照常执行。
anonymousCallEnabled选填此 Script 是否可以不经认证通过 /execute/anonymous 调用。布尔值,省略时为 false。参见下面的匿名调用。PUT 为整体替换,省略时会重置为 false。

definition(ScriptDefinition)的键:

键必填说明
method必填调用此 Script 的 HTTP 方法。为 Get、Post、Put、Patch、Delete 之一。执行时按此值匹配。
statements必填要执行的 Statement 的有序数组。至少 1 个。
payloadSchema选填JSON Schema。若指定,则在执行前用此模式校验请求 payload。
secrets选填机密值列表。项目为 { "key", "value", "description" },在 Statement 中以 { /secrets/<key> } 读取。value 由 WEEGLOO 加密后安全保存,在响应中以原始值返回。PUT 为整体替换,省略时已声明的机密值会被删除。若 Statement 仍在以 { /secrets/… } 引用,则不会被删除,而是拒绝保存。规则参见安全模型的 secrets。

放入 statements 数组的每个 Statement 的种类和字段在 Statement 目录 中介绍,用于传递值的 { /pointer } 表达式在 值表达式 中介绍。

上面示例 "t6-http" 的 definition 中 method 为 Post,先用 Http Statement 调用外部 API,再用 Return Statement 返回其结果。像 Http 这样存在外部调用的 Statement 会声明属于自己的时间,这部分时间会加到一次执行可用的时间上(参见一次执行可用的时间)。

约束

对象约束
name1~64 个字符,必填。
definition.statements至少 1 个,必填。
每个定义的外部调用(Http、EmailSend)按套餐(参见定价方案)。
每个定义的全部 Statement按套餐(参见定价方案,含嵌套)。
每个定义的 SetVar最多 10 个(默认值,含嵌套)。
Regex.pattern最多 128 个字符。
definition.secrets最多 20 个。key 为 164 个字符(英文字母、数字、_、-)且在一个 Script 内唯一,value 为 14,096 个字符,description 为 0~128 个字符(字段为必填)。
anonymousCallEnabled 为 true 的定义where 中不能使用 createdBy: ":self"。参见下面的匿名调用。
被其他资源引用的 Script无法删除。Webhook 以关联动作引用它,或 Scheduler 以执行对象引用它时,删除会被拒绝,返回的错误码因引用方而异(已关闭的 Scheduler 也一样。参见错误)。

上述静态约束会在 Script 保存(创建、修改)时进行检查,违反时保存会被拒绝。外部调用数与全部 Statement 数不是校验错误,而是套餐限额,因此同一个定义在更高套餐上是允许的。

保存时还会一并检查权限与资源种类。

  • 检查创建者是否实际拥有这些 Statement 所使用的资源、动作权限(只要缺少任意一项,保存就会被拒绝。参见错误)。处理会员(ServiceUser)的 Statement 不是通过权限映射检查,而是通过 SpaceRole settings 中的 SETTING_SERVICE_LOGIN 检查。
  • 若含有创建或删除会员(ServiceUser)的 Statement,则拒绝保存。Script 无法创建或删除会员,因此任何角色都无法保存。会员上被允许的改动只有 ResourceUpdate、ResourcePatch 的 roleOverride 与 enableLogin(参见处理会员目录)。

详细规则、时间预算,以及运行中检查的值长度上限,在 执行语义、约束与安全 中介绍。

Script 是计费资源,每个 Organization 的数量按套餐受限(Free 10 / Basic 30 / Pro 100 / Enterprise 无限制)。达到上限后,新的 Script 创建会被拒绝(参见各套餐数量限额)。

匿名调用 (anonymousCallEnabled)

把 anonymousCallEnabled 设为 true 后,该 Script 也可以通过无需认证的专用路径执行。

{method} https://script.weegloo.com/v1/spaces/{spaceId}/scripts/{scriptId}/execute/anonymous

需要用到它的情况很少。 它是为那种必须向我们发送回调、却因为不支持自定义请求头而无法携带 Access Token 的第三方(支付服务商 PG、MoR 等)准备的装置。凡是能够携带令牌的调用方,都使用认证路径(/execute)。

  • 认证路径保持原样。 /execute 仍然要求 Bearer 令牌与 Script 的 Execute 权限。变成无认证的只有 /execute/anonymous 这一条路径。
  • 它不接受令牌。 即使携带令牌发送也会被忽略,执行始终是作者身份。若要以调用方身份执行,请使用 /execute。
  • 必须同时通过两道门禁。 anonymousCallEnabled 为 false 时会作为未经认证的访问被拒绝,directCallEnabled 为 false 时则因直接调用被封锁而拒绝。返回的错误码取决于卡在哪一道门禁(参见错误)。由于先看是否允许匿名,因此没有资格的调用方无法探知该 Script 的配置状态。
  • 之后与 /execute 相同。请求的 HTTP 方法必须与 definition.method 一致,并且会消耗 Organization 的 Script 执行配额,同时被计入使用量。
  • 这条路径与认证执行路径位于同一个 Script 主机(https://script.weegloo.com/v1)上。

以作者身份执行

由于没有调用方,执行是以创建该 Script 的用户(sys.createdBy)的身份进行的。

  • Script 中创建或修改的 Content、Media 的 createdBy、updatedBy 会写入作者(不是匿名调用方。因为没有其他可归属的身份)。
  • where 中的 createdBy: ":self" 也不会解析为调用方,而是解析为作者。若把以认证调用方为前提写好的所有权过滤器原样留下并开启匿名,就会悄悄开放作者的资源,因此那样的定义从一开始就无法保存(见下)。

保存时的追加检查

anonymousCallEnabled 为 true 的 Script 会再多加一条规则。

规则代码
ResourceFind、ResourceForEach 的 where 中不能使用 createdBy: ":self"参见错误

因为匿名调用没有调用方身份,:self 会解析为作者。这样可以在保存时就阻止以认证调用方为前提写好的所有权过滤器被悄悄突破。

实质上的认证由 Script 自己完成

这条路径上没有平台提供的认证。知道该 URL 的任何人都可以调用,而且该调用会消耗 Organization 的 Script 执行配额,也没有单独的速率限制。 因此匿名 Script 必须自己校验所收到的请求。

  • 在最前面放上 Signature,校验针对 { /rawPayload } 的签名,未通过就用 Return 就地终止。完整示例见 Cookbook 的 Webhook 签名校验。
  • 再用 /now 一并检查 replay window,就能阻止把过去的请求重新发送(/now)。
  • 匿名 Script 中只放该回调实际需要做的事。Script 是受委托作者的权限来执行的,因此放进去多少,就等于无认证地开放了多少(安全模型)。

ScriptLog

Script 每执行一次就会留下一条记录。这条记录就是 ScriptLog。它只能查询,没有创建、修改、删除端点。路径是 /spaces/{spaceId}/scripts/{scriptId}/logs,基准 URL 不是执行主机,而是 CMA 的 https://cma.weegloo.com/v1。要读取它,需要该 Script 的 Read 权限。

{
  "sys": {
    "id": "3trmXRM7pLdV5Rz8kWq2NcHfJt4bYs",
    "type": "ScriptLog",
    "space": { "sys": { "id": "6jSUUAWT", "type": "Refer", "targetType": "Space" } },
    "script": { "sys": { "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK", "type": "Refer", "targetType": "Script" } },
    "trigger": { "sys": { "id": "3trmXRMZcTAjDnphewjj1AaxYcaxlK", "type": "Refer", "targetType": "Script" } },
    "requestId": "3trmXRM9wTbK4Vz7hLp2QsNdRf6cYm",
    "returned": true,
    "value": { "status": 200, "prompt": "夏季连衣裙商品说明 3 行" },
    "success": true,
    "statusCode": 200,
    "durationMs": 195,
    "createdBy": { "sys": { "id": "3p4tcFbQYJNvYTBJf2rYKr42xegQLJ", "type": "Refer", "targetType": "User" } },
    "createdAt": "2026-07-15T12:41:03.902Z",
    "updatedBy": { "sys": { "id": "3p4tcFbQYJNvYTBJf2rYKr42xegQLJ", "type": "Refer", "targetType": "User" } },
    "updatedAt": "2026-07-15T12:41:03.902Z"
  }
}

所有值都在 sys 之中,没有正文属性。没有值的键会从响应中省略。

属性类型说明
idstring记录的唯一标识符。
typestring始终为 "ScriptLog"。
spaceRefer<Space>此记录所属的 Space。
scriptRefer<Script>被执行的 Script。
triggerRefer引发这次执行的对象。参见下文说明。
requestIdstring这次执行的标识符。与执行响应信封中的 requestId 是同一个值。
returnedboolean是否到达了 Return Statement。
valueany所到达的 Return 返回的值。对象、数组、标量都会原样载入。若失败,这里装的就是失败原因。
successboolean是否成功。
statusCodeinteger所到达的 Return 定下的状态码。
durationMsinteger执行耗时(毫秒)。
createdByRefer<User> 或 Refer<ServiceUser>此记录所归属的身份。参见下文说明。
createdAtstring (date-time)记录创建时间。
updatedByRefer<User> 或 Refer<ServiceUser>与 createdBy 相同。
updatedAtstring (date-time)与 createdAt 相同。

trigger 指向引发这次执行的对象。直接调用时是该 Script 自身,通过 Webhook 的关联动作执行时是那个 Webhook,由 Scheduler 运行时则是那个 Scheduler。

requestId 与执行响应信封中的 requestId 是同一个值。调用方在自己收到的响应中查找那次执行的记录时,以这个值为依据。

记录在执行结束后写入一次,之后不再变化。成功的执行在 1 小时后消失,失败的执行在 3 天后消失。 需要保留更久的值,请在 Script 中保存为 Content。

createdBy 指向这次执行是以哪个身份完成的。用 Weegloo User 令牌调用的执行是那位用户,用会员(ServiceUser)令牌调用的执行是那位会员。没有调用方的执行,其身份来自触发者。匿名执行是该 Script 的作者,Scheduler 运行的执行是创建该 Scheduler 的用户(可能与 Script 作者不同),Webhook 执行的则是创建该 Webhook 的用户。Webhook 的 runAs 只决定 Script 内的操作以谁的名义进行,并不改变这条日志的归属。

错误

以下是调用或删除 Script 时出现的错误码。保存定义时出现的错误码在执行语义、约束与安全的错误中,违反值表达式规则的错误码在值表达式的错误中,所有资源共通的错误码在通用错误中。

错误码条件
WGL422066要删除的 Script 正被某个 Webhook 以关联动作引用(已关闭的 Webhook 也一样)。
WGL422110要删除的 Script 正被某个 Scheduler 以执行对象引用(已关闭的 Scheduler 也一样)。
WGL401001对 anonymousCallEnabled 为 false 的 Script 调用了匿名执行路径(/execute/anonymous)。
WGL422062对 directCallEnabled 为 false 的 Script 通过执行路径(/execute、/execute/anonymous)进行了直接调用。
WGL400007执行请求的 HTTP 方法与该 Script 的 definition.method 不同。发送了请求正文而它不是 JSON 对象时,以及在设有 definition.payloadSchema 的 Script 中请求正文不满足该 schema 时,也以同一个错误码拒绝。
WGL408002执行超出时间预算而被中断。截至中断处的执行记录会保留在 ScriptLog 中。

API

下面五个端点(列表、查询、创建、修改、删除)的基准 URL 是 CMA 的 https://cma.weegloo.com/v1,Authorization 头中需要用于认证 CMA 的 Bearer 令牌。修改操作为实现乐观并发控制,必须一并发送 X-Weegloo-Version 头(当前资源的 sys.version)。最下面两个 ScriptLog 查询端点也使用相同的 CMA 基准 URL。

两个执行端点的基准 URL 是专用 Script 主机 https://script.weegloo.com/v1。已认证的执行(/execute)同时接受 Weegloo User 身份的 Bearer 令牌与会员(ServiceUser)身份的 Bearer 令牌,无论哪一种,调用方都需要该 Script 的 Execute 权限。

只有匿名执行(/execute/anonymous)例外,不要求认证头。 它位于同一个 Script 主机上,并且只有在该 Script 开启了 anonymousCallEnabled 时才可达(参见上面的匿名调用)。

上面认证执行示例的响应中没有 return。因为目标 Script 未到达带值的 Return 就结束了(此时 statusCode 为默认值 200)。像匿名执行示例那样用 Return 返回值时,响应中会带有 return(若 Return.isError 为真,则为 error)。响应的完整规则在 Script 概述的请求与响应 中介绍。