策略
Fystack 策略是针对敏感钱包操作的可编程防护机制。策略以工作区为目标,可选地限定到特定钱包,并包含若干规则,这些规则会针对结构化的操作 payload 评估表达式。
规则会在以下四种操作上运行:
- Name
- withdrawal.create
- Type
- trigger_action
- Description
在创建提现之前评估。
DENY会阻止该请求。匹配的ALLOW会绕过交易审批,让提现直接进入签名阶段。
- Name
- web3.transfer
- Type
- trigger_action
- Description
当通过 Web3 原始交易 API 发送原生币或 ERC-20 转账时评估。它使用与
withdrawal.create相同的withdrawal.*字段,因此同一个条件在两个触发器上含义一致。由于这些转账不是提现,速率(velocity)字段不可用。ERC-20 转账还会作为web3.contract_call进行评估。
- Name
- web3.contract_call
- Type
- trigger_action
- Description
在 EVM 合约调用和 ERC-20 代币转账发送去签名之前评估。
DENY会将该活动记录为denied_by_policy。匹配的ALLOW会跳过交易审批并直接进入签名阶段。
- Name
- web3.sign_message
- Type
- trigger_action
- Description
当钱包被要求使用
personal_sign、eth_sign或eth_signTypedData_v4签名消息时评估。仅支持拒绝:签名消息始终需要经过审批。
策略 schema 由 Apex 中的后端操作 schema 生成。构建 UI 构建器或动态校验字段可用性时,请使用获取策略 schema。如需现成的规则,请参阅策略模板。
策略结构
策略是容器,规则是可执行单元。
{
"name": "Large withdrawal guard",
"approval_group_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"wallet_ids": [],
"rules": [
{
"trigger_action": "withdrawal.create",
"condition": "withdrawal.value_usd > 10000 && !withdrawal.is_whitelisted",
"effect": "DENY"
}
]
}
- Name
- approval_group_id
- Type
- string
- Description
负责审核策略创建、策略编辑、策略删除和规则变更的审批组。
- Name
- wallet_ids
- Type
- string[]
- Description
该策略适用的钱包。空数组表示工作区中的所有钱包。
- Name
- rules
- Type
- array
- Description
最多 50 条规则。每条规则包含
trigger_action、condition、effect,以及可选的description和is_enabled。
策略状态
- Name
- pending
- Type
- status
- Description
已创建但尚未批准。待处理的策略不会被评估。
- Name
- active
- Type
- status
- Description
已批准并生效。评估器只加载 active 状态的策略。
- Name
- inactive
- Type
- status
- Description
已禁用,不会被评估。
- Name
- rejected
- Type
- status
- Description
在审批中被拒绝,不会被评估。
策略评估
对于每个受保护的请求,Fystack 会加载工作区的 active 策略,编译已启用的规则,按操作和钱包目标筛选匹配项,然后按以下方式得出结果:
- 如果任一匹配规则的
effect: "DENY",则该操作被阻止。 - 否则,如果任一匹配规则的
effect: "ALLOW",则该操作继续执行,并绕过交易审批。 - 否则,表示没有策略规则匹配。该操作继续走正常的审批流程。
DENY 始终优先于 ALLOW,因此规则顺序永远不会改变结果。在胜出的 effect 中,按声明顺序第一个匹配的规则用于归因,因此 API 可以返回稳定的 rule_id 和策略原因。
不存在单独的 "require approval" effect。对于没有任何 ALLOW 规则匹配的操作,默认都需要审批。
评估采用失败即拒绝(fail-closed)原则。缓存、数据库、编译或运行时评估出现故障时,操作都会被拒绝。每次评估的超时时间为 100 ms。
作用域与缓存
策略以工作区为作用域。Apex 会为每个工作区缓存一个编译后的策略包,并在策略被批准、拒绝以及钱包目标变更后使其失效。钱包筛选在评估时进行,因此一个工作区的策略包可以服务于该工作区内的所有钱包。
条件
condition 是一个必须返回布尔值的表达式。通过分区和字段名引用字段,例如 principal.role、withdrawal.value_usd、wallet.purpose 或 resource.method_selector。
可使用常规的布尔、比较和成员运算符:
&& || ! == != > >= < <= in
in 用于检查是否属于某个列表字面量或列表字段,例如 principal.api_key_id in ["<api_key_id>"] 或 "0x…" in resource.permit_tokens。
示例:
- Name
- 拒绝大额且未加入白名单的提现
- Type
- DENY
- Description
withdrawal.value_usd > 10000 && !withdrawal.is_whitelisted
- Name
- 每个钱包每天上限 $100,000
- Type
- DENY
- Description
wallet.projected_outflow_24h > 100000
- Name
- 将托管资金保留在工作区内
- Type
- DENY
- Description
wallet.purpose == "custody" && !withdrawal.destination_is_internal
- Name
- 为支付 API key 绕过审批
- Type
- ALLOW
- Description
principal.initiator_type == "api_key" && principal.api_key_id in ["<api_key_id>"] && withdrawal.value_usd < 1000
- Name
- 为添加已久的地址簿条目绕过审批
- Type
- ALLOW
- Description
withdrawal.is_whitelisted && withdrawal.address_age_sec >= 86400 && withdrawal.value_usd <= 1000
- Name
- 拒绝周末的高额提现
- Type
- DENY
- Description
(context.day_of_week == "Saturday" || context.day_of_week == "Sunday") && withdrawal.value_usd > 25000
- Name
- 拒绝高 gas 的 ERC-20 转账
- Type
- DENY
- Description
resource.method_selector == "0xa9059cbb" && resource.gas_limit > 100000
- Name
- 拒绝无限额的代币 permit
- Type
- DENY
- Description
resource.is_permit && resource.permit_amount_is_unlimited
resource.decoded_args 是动态的。读取动态字段前请先用 has(...) 进行判断,例如 has(resource.decoded_args.to) && resource.decoded_args.to == "0x000000000000000000000000000000000000dead"。
引用字段
schema 中标记了 ref 的字段保存的是另一个工作区实体的 ID 或代码:workspace_user、api_key、wallet、address_book、network 或 asset_symbol。条件构建器应为这些字段渲染选择器。
保存规则时,Fystack 会检查每个被引用的 ID 是否属于你的工作区。如果某个实体之后被删除或吊销,规则仍保留该 ID,只会匹配得更少,绝不会更多。
操作 schema
操作 schema 定义了条件中可用的字段。标记为 deprecated 的字段在已有规则中仍会被评估,但不应在新规则中使用。
通用字段
每种触发操作都提供以下字段。
- Name
- principal.user_id
- Type
- string · ref workspace_user
- Description
发起操作的工作区成员 ID。当发起方为 API key 时为空。
- Name
- principal.role
- Type
- string
- Description
工作区角色。取值为
owner、admin、signer、proposer或viewer之一。
- Name
- principal.initiator_type
- Type
- string
- Description
网页会话为
user,API key 为api_key。
- Name
- principal.api_key_id
- Type
- string · ref api_key
- Description
发起操作的 API key 的 ID。网页会话时为空,因此请与
principal.initiator_type结合使用。
- Name
- principal.user_email
- Type
- string · deprecated
- Description
发起用户的邮箱。由于邮箱可能变更,请改用
principal.user_id。
- Name
- wallet.id
- Type
- string · ref wallet
- Description
源钱包 ID。用于在一个策略内针对特定钱包的规则。
- Name
- wallet.purpose
- Type
- string
- Description
源钱包用途。取值为
general、custody、payment、user、one_time_use、gas_tank或deployment之一。
- Name
- wallet.type
- Type
- string
- Description
源钱包类型。
standard或mpc。
- Name
- context.hour
- Type
- integer
- Description
评估时的 UTC 小时,取值
0到23。
- Name
- context.day_of_week
- Type
- string
- Description
UTC 星期名称,例如
Monday或Saturday。
提现字段
适用于 withdrawal.create 和 web3.transfer。
- Name
- withdrawal.amount
- Type
- number
- Description
请求的资产数量。
- Name
- withdrawal.value_usd
- Type
- number
- Description
请求的 USD 价值。
- Name
- withdrawal.asset_symbol
- Type
- string · ref asset_symbol
- Description
资产符号,例如
USDT、ETH或BTC。
- Name
- withdrawal.asset_is_native
- Type
- boolean
- Description
该资产是否为网络原生资产。
- Name
- withdrawal.asset_is_known
- Type
- boolean
- Description
该代币是否在 Fystack 资产目录中。为
false时,amount、value_usd和asset_symbol为空,因此如有需要,请显式拒绝未知代币。
- Name
- withdrawal.token_address
- Type
- string
- Description
代币合约地址。原生币时为空。
- Name
- withdrawal.destination_address
- Type
- string
- Description
收款地址。
- Name
- withdrawal.network_code
- Type
- string · ref network
- Description
内部网络代码。
- Name
- withdrawal.is_whitelisted
- Type
- boolean
- Description
目标地址是否存在于工作区的任一地址簿条目中。
- Name
- withdrawal.address_book_id
- Type
- string · ref address_book
- Description
包含目标地址的地址簿条目。一个条目涵盖其下的所有地址,因此条目可以作为命名列表使用。
- Name
- withdrawal.address_age_sec
- Type
- number
- Description
目标地址被添加到其地址簿条目以来的秒数。可用于对新添加的收款方设置冷却期规则。
- Name
- withdrawal.destination_is_internal
- Type
- boolean
- Description
目标是否为同一工作区内的另一个钱包。
- Name
- withdrawal.destination_wallet_id
- Type
- string · ref wallet
- Description
当目标为内部钱包时的目标钱包。
提现速率字段
仅适用于 withdrawal.create。除非另有说明,所有值均以 USD 计。
- Name
- wallet.outflow_1h / outflow_6h / outflow_24h
- Type
- number
- Description
源钱包在过去 1、6 或 24 小时内的已实现流出量。
- Name
- wallet.withdrawal_count_1h
- Type
- integer
- Description
源钱包在过去一小时内的提现尝试次数。
- Name
- wallet.pending_outflow
- Type
- number
- Description
源钱包中尚未执行的提现总价值。
- Name
- wallet.projected_outflow_24h
- Type
- number
- Description
源钱包的预计流出量:过去 24 小时已实现流出量,加上待处理流出量,再加上正在检查的这笔提现。
- Name
- wallet.asset_projected_outflow_24h
- Type
- number
- Description
以所提现资产为单位计算的源钱包同类预计值,例如每天最多 5 BTC。
- Name
- workspace.outflow_1h / outflow_6h / outflow_24h
- Type
- number
- Description
工作区在过去 1、6 或 24 小时内的已实现流出量。
- Name
- workspace.withdrawal_count_1h
- Type
- integer
- Description
工作区在过去一小时内的提现尝试次数。
- Name
- workspace.pending_outflow
- Type
- number
- Description
工作区中尚未执行的提现总价值。
- Name
- workspace.projected_outflow_24h
- Type
- number
- Description
工作区预计流出量:过去 24 小时已实现流出量,加上待处理流出量,再加上正在检查的这笔提现。
- Name
- workspace.network_outflow_1h / network_outflow_6h / network_outflow_24h
- Type
- number
- Description
工作区在当前网络上过去 1、6 或 24 小时内的已实现流出量。
- Name
- workspace.network_withdrawal_count_1h
- Type
- integer
- Description
工作区在当前网络上过去一小时内的提现尝试次数。
- Name
- workspace.network_pending_outflow
- Type
- number
- Description
工作区在当前网络上的待处理流出量。
- Name
- workspace.network_projected_outflow_24h
- Type
- number
- Description
工作区在当前网络上的预计流出量。
- Name
- workspace.initiator_projected_outflow_24h
- Type
- number
- Description
由同一成员或 API key 在整个工作区内创建的提现的预计流出量。
流出量和计数字段均为已实现值:只有当提现达到已执行或成功的终态后才会被计入。待处理流出量统计的是正在等待审批、排队中或正在补充 gas 的提现,无论其存在多久。
当某条 active 规则使用了待处理或预计字段时,Fystack 会逐个评估该工作区的提现,因此两个并发请求不可能同时通过同一限额。等待超过 5 秒仍未轮到的请求会以 HTTP 429 被拒绝,可以重试。
web3.contract_call 字段
- Name
- resource.network_code
- Type
- string · ref network
- Description
内部网络代码。
- Name
- resource.contract_address
- Type
- string
- Description
来自原始交易
to字段的小写合约地址。
- Name
- resource.method_selector
- Type
- string
- Description
小写的 4 字节选择器,例如
0xa9059cbb。
- Name
- resource.method_name
- Type
- string
- Description
请求元数据中提供的方法名(如有)。
- Name
- resource.value_wei
- Type
- string
- Description
随调用发送的原生币数量,以字符串表示。
- Name
- resource.gas_limit
- Type
- integer
- Description
原始交易中的 gas limit。
- Name
- resource.decoded_args
- Type
- map
- Description
当 Fystack 能识别该调用时解码出的参数。ERC-20
transfer会提供to和value。
web3.sign_message 字段
- Name
- resource.method
- Type
- string
- Description
签名方法。取值为
personal_sign、eth_sign或eth_signTypedData_v4之一。
- Name
- resource.network_code
- Type
- string · ref network
- Description
内部网络代码。
- Name
- resource.typed_data_primary_type
- Type
- string
- Description
EIP-712 primary type,用于类型化数据消息。
- Name
- resource.typed_data_domain_name
- Type
- string
- Description
EIP-712 domain name,用于类型化数据消息。
- Name
- resource.typed_data_verifying_contract
- Type
- string
- Description
EIP-712 verifying contract,用于类型化数据消息。
- Name
- resource.is_permit
- Type
- boolean
- Description
对于 EIP-2612、DAI 和 Permit2 消息为
true,这类消息允许 spender 之后无需再次签名即可转移代币。
- Name
- resource.permit_spender
- Type
- string
- Description
permit 授权的地址。
- Name
- resource.permit_tokens
- Type
- string[]
- Description
permit 涵盖的代币合约。可与
in一起使用,例如"0x…" in resource.permit_tokens。
- Name
- resource.permit_amount_is_unlimited
- Type
- boolean
- Description
对于最大额度授权(2159 或以上,或设置了
allowed的 DAI permit)为true。
- Name
- resource.permit_deadline
- Type
- integer
- Description
permit 或其签名过期的 Unix 时间。消息中没有时为
0。
审批生命周期
创建、更新和删除策略的操作都受审批管控。变更操作会创建一个 policy 审批请求,并返回 status: "pending_approval" 以及 approval_request_id。只有在审批组达到门限后,策略变更才会生效。
当父策略配置了审批组时,规则的创建、更新和删除操作也遵循相同的模式。待处理的修订会保存字段级差异,以供审计和审核。
通过 /wallets 更新钱包目标会在校验和缓存失效后立即生效。如果希望钱包目标的变更作为更大的策略修订的一部分接受审核,请使用策略更新 endpoint。
认证
策略 API endpoint 接受已签名的 API key 请求或 bearer access token。
- Name
- ACCESS-API-KEY
- Type
- header
- Description
用于 HMAC 认证请求的 API key UUID。
- Name
- ACCESS-TIMESTAMP
- Type
- header
- Description
用于构建 HMAC 签名的 UNIX 时间戳(秒)。
- Name
- ACCESS-SIGN
- Type
- header
- Description
Base64 编码的 HMAC 签名。签名格式请参阅认证。
- Name
- Authorization
- Type
- header
- Description
用于用户会话请求的 bearer access token。
策略审批决策 endpoint 仍然是用户会话 endpoint。批准和拒绝审批请求时请使用 bearer access token。
响应信封
成功的 JSON 响应使用标准的 Fystack 信封格式。
- Name
- success
- Type
- boolean
- Description
请求成功时为
true。
- Name
- message
- Type
- string
- Description
响应消息,通常为
success。
- Name
- code
- Type
- integer
- Description
数字结果代码。成功响应使用
0。
- Name
- data
- Type
- object | array | null
- Description
特定于 endpoint 的响应 payload。
校验错误使用相同的信封格式,其中 success: false,并包含 errors 数组。
数据类型
Policy
- Name
- id
- Type
- string
- Description
策略 UUID。
- Name
- created_at
- Type
- string
- Description
策略创建时间的 ISO 时间戳。
- Name
- updated_at
- Type
- string
- Description
策略最后更新时间的 ISO 时间戳。
- Name
- name
- Type
- string
- Description
策略名称。3 到 100 个字符。
- Name
- description
- Type
- string
- Description
可选描述。最多 500 个字符。
- Name
- status
- Type
- string
- Description
取值为
pending、rejected、active或inactive之一。
- Name
- version
- Type
- integer
- Description
策略版本号。
- Name
- workspace_id
- Type
- string
- Description
工作区 UUID。
- Name
- approval_group_id
- Type
- string | null
- Description
分配给该策略的审批组 UUID。
- Name
- wallet_ids
- Type
- string[]
- Description
目标钱包 UUID。空数组表示该策略针对工作区中的所有钱包。
- Name
- rules
- Type
- PolicyRule[]
- Description
在预加载规则的 endpoint 中返回。
- Name
- approval_group
- Type
- object
- Description
在预加载审批组的 endpoint 中返回。
- Name
- pending_approval_request
- Type
- object
- Description
当该策略存在待处理的审批请求时返回。
PolicyRule
- Name
- id
- Type
- string
- Description
规则 UUID。
- Name
- policy_id
- Type
- string
- Description
父策略 UUID。
- Name
- trigger_action
- Type
- string
- Description
取值为
withdrawal.create、web3.transfer、web3.contract_call或web3.sign_message之一。
- Name
- condition
- Type
- string
- Description
布尔条件表达式。1 到 4000 个字符。
- Name
- effect
- Type
- string
- Description
取值为
ALLOW或DENY之一。
- Name
- description
- Type
- string
- Description
可选描述。最多 500 个字符。
- Name
- is_enabled
- Type
- boolean
- Description
规则是否启用。创建时如省略则默认为
true。
变更响应
策略和规则的变更 endpoint 会在 data 中返回变更 payload。
- Name
- status
- Type
- string
- Description
取值为
applied、pending_approval或deleted之一,取决于具体操作。
- Name
- policy
- Type
- Policy
- Description
适用时由策略变更 endpoint 返回。
- Name
- rule
- Type
- PolicyRule
- Description
适用时由规则变更 endpoint 返回。
- Name
- approval_request_id
- Type
- string
- Description
当变更正在等待审批时返回。
获取策略 schema
返回条件可以引用的字段,按 trigger_action 和分区分组。可将此 endpoint 用于条件构建器和客户端预览。
每个字段都有 name 和 type。可选键:
- Name
- enum
- Type
- string[]
- Description
该字段允许的取值。
- Name
- ref
- Type
- string
- Description
该字段引用的实体。请为其渲染选择器。参阅引用字段。
- Name
- deprecated
- Type
- boolean
- Description
在已有规则中仍会被评估。请在新规则构建器中隐藏它。
Request
curl -X GET https://api.fystack.io/api/v1/policy/schema \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
Response
200{
"success": true,
"message": "success",
"code": 0,
"data": {
"withdrawal.create": {
"principal": [
{ "name": "user_email", "type": "string", "deprecated": true },
{ "name": "user_id", "type": "string", "ref": "workspace_user" },
{ "name": "role", "type": "string", "enum": ["owner", "admin", "signer", "proposer", "viewer"] },
{ "name": "initiator_type", "type": "string", "enum": ["user", "api_key"] },
{ "name": "api_key_id", "type": "string", "ref": "api_key" }
],
"withdrawal": [
{ "name": "amount", "type": "number" },
{ "name": "value_usd", "type": "number" },
{ "name": "asset_symbol", "type": "string", "ref": "asset_symbol" },
{ "name": "asset_is_native", "type": "boolean" },
{ "name": "asset_is_known", "type": "boolean" },
{ "name": "token_address", "type": "string" },
{ "name": "destination_address", "type": "string" },
{ "name": "network_code", "type": "string", "ref": "network" },
{ "name": "is_whitelisted", "type": "boolean" },
{ "name": "address_age_sec", "type": "number" },
{ "name": "address_book_id", "type": "string", "ref": "address_book" },
{ "name": "destination_is_internal", "type": "boolean" },
{ "name": "destination_wallet_id", "type": "string", "ref": "wallet" }
],
"wallet": [
{ "name": "id", "type": "string", "ref": "wallet" },
{ "name": "purpose", "type": "string", "enum": ["general", "custody", "payment", "user", "one_time_use", "gas_tank", "deployment"] },
{ "name": "type", "type": "string", "enum": ["standard", "mpc"] },
{ "name": "outflow_1h", "type": "number" },
{ "name": "outflow_6h", "type": "number" },
{ "name": "outflow_24h", "type": "number" },
{ "name": "withdrawal_count_1h", "type": "integer" },
{ "name": "pending_outflow", "type": "number" },
{ "name": "projected_outflow_24h", "type": "number" },
{ "name": "asset_projected_outflow_24h", "type": "number" }
],
"workspace": [
{ "name": "outflow_1h", "type": "number" },
{ "name": "outflow_6h", "type": "number" },
{ "name": "outflow_24h", "type": "number" },
{ "name": "withdrawal_count_1h", "type": "integer" },
{ "name": "network_outflow_1h", "type": "number" },
{ "name": "network_outflow_6h", "type": "number" },
{ "name": "network_outflow_24h", "type": "number" },
{ "name": "network_withdrawal_count_1h", "type": "integer" },
{ "name": "pending_outflow", "type": "number" },
{ "name": "projected_outflow_24h", "type": "number" },
{ "name": "network_pending_outflow", "type": "number" },
{ "name": "network_projected_outflow_24h", "type": "number" },
{ "name": "initiator_projected_outflow_24h", "type": "number" }
],
"context": [
{ "name": "hour", "type": "integer" },
{ "name": "day_of_week", "type": "string" }
]
},
"web3.transfer": {
"principal": [ "... same as withdrawal.create ..." ],
"withdrawal": [ "... same as withdrawal.create ..." ],
"wallet": [
{ "name": "id", "type": "string", "ref": "wallet" },
{ "name": "purpose", "type": "string", "enum": ["general", "custody", "payment", "user", "one_time_use", "gas_tank", "deployment"] },
{ "name": "type", "type": "string", "enum": ["standard", "mpc"] }
],
"context": [ "... same as withdrawal.create ..." ]
},
"web3.contract_call": {
"principal": [ "... same as withdrawal.create ..." ],
"resource": [
{ "name": "network_code", "type": "string", "ref": "network" },
{ "name": "contract_address", "type": "string" },
{ "name": "method_selector", "type": "string" },
{ "name": "method_name", "type": "string" },
{ "name": "value_wei", "type": "string" },
{ "name": "gas_limit", "type": "integer" },
{ "name": "decoded_args", "type": "map" }
],
"wallet": [ "... id, purpose, type ..." ],
"context": [ "... same as withdrawal.create ..." ]
},
"web3.sign_message": {
"principal": [ "... same as withdrawal.create ..." ],
"resource": [
{ "name": "method", "type": "string", "enum": ["personal_sign", "eth_sign", "eth_signTypedData_v4"] },
{ "name": "network_code", "type": "string", "ref": "network" },
{ "name": "typed_data_primary_type", "type": "string" },
{ "name": "typed_data_domain_name", "type": "string" },
{ "name": "typed_data_verifying_contract", "type": "string" },
{ "name": "is_permit", "type": "boolean" },
{ "name": "permit_spender", "type": "string" },
{ "name": "permit_tokens", "type": "string[]" },
{ "name": "permit_amount_is_unlimited", "type": "boolean" },
{ "name": "permit_deadline", "type": "integer" }
],
"wallet": [ "... id, purpose, type ..." ],
"context": [ "... same as withdrawal.create ..." ]
}
}
}
校验规则
校验规则内容,而不创建或更新规则。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
请求体参数
- Name
- trigger_action
- Type
- string
- Required
- required
- Description
取值为
withdrawal.create、web3.transfer、web3.contract_call或web3.sign_message之一。
- Name
- condition
- Type
- string
- Required
- required
- Description
1 到 4000 个字符。必须能编译为布尔表达式。
- Name
- effect
- Type
- string
- Required
- required
- Description
取值为
ALLOW或DENY之一。web3.sign_message规则仅支持拒绝。
响应数据
- Name
- valid
- Type
- boolean
- Description
规则内容校验通过时为
true。
Request
curl -X POST https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/rules/validate \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature==" \
-H "Content-Type: application/json" \
-d '{
"trigger_action": "withdrawal.create",
"condition": "withdrawal.value_usd > 10000",
"effect": "DENY"
}'
Response
200{
"success": true,
"message": "success",
"code": 0,
"data": { "valid": true }
}
创建策略
创建一个策略变更。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
请求体参数
- Name
- name
- Type
- string
- Required
- required
- Description
3 到 100 个字符。
- Name
- description
- Type
- string
- Description
Optional. Up to 500 characters.
- Name
- approval_group_id
- Type
- string
- Required
- required
- Description
审批组 UUID。
- Name
- wallet_ids
- Type
- string[]
- Description
可选。最多 500 个钱包 UUID。
- Name
- rules
- Type
- PolicyRuleCreate[]
- Description
可选。最多 50 条规则。
Request
curl -X POST https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature==" \
-H "Content-Type: application/json" \
-d '{
"name": "Large withdrawal guard",
"approval_group_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"wallet_ids": [],
"rules": [
{
"trigger_action": "withdrawal.create",
"condition": "withdrawal.value_usd > 10000",
"effect": "DENY"
}
]
}'
Response
200{
"success": true,
"message": "success",
"code": 0,
"data": {
"status": "pending_approval",
"approval_request_id": "b7e2a1c4-9d8f-4a3b-8c1d-2e3f4a5b6c7d",
"policy": {
"id": "9c8b7a6d-5e4f-3210-9a8b-7c6d5e4f3210",
"name": "Large withdrawal guard",
"status": "pending",
"version": 1,
"wallet_ids": []
}
}
}
列出策略
返回工作区中的策略。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
查询参数
- Name
- status
- Type
- string
- Description
可选。取值为
pending、rejected、active或inactive之一。
- Name
- limit
- Type
- integer
- Description
可选。最大值
1000。
- Name
- offset
- Type
- integer
- Description
可选。最大值
100000。
响应数据
- Name
- data
- Type
- Policy[]
- Description
策略对象数组。
Request
curl -X GET "https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies?status=active&limit=20&offset=0" \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
获取策略
返回单个策略。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
响应数据
- Name
- data
- Type
- Policy
- Description
策略对象,包含规则、审批组以及待处理的审批请求(如有)。
Request
curl -X GET https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id} \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
更新策略
更新策略字段。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
请求体参数
- Name
- name
- Type
- string
- Description
可选。3 到 100 个字符。
- Name
- description
- Type
- string
- Description
Optional. Up to 500 characters.
- Name
- approval_group_id
- Type
- string
- Description
可选的审批组 UUID。
- Name
- wallet_ids
- Type
- string[]
- Description
可选。最多 500 个钱包 UUID。传入空数组表示针对所有钱包。
- Name
- rules
- Type
- PolicyRuleCreate[]
- Description
可选。传入时会替换完整的规则集。传入空数组可清除所有规则。
Request
curl -X PUT https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id} \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature==" \
-H "Content-Type: application/json" \
-d '{
"description": "Updated policy description",
"wallet_ids": ["e0851607-417a-475a-b399-5f3aa262b81d"]
}'
删除策略
删除策略,或创建一个等待审批的删除变更。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
响应数据
- Name
- data
- Type
- Mutation response
- Description
策略变更响应。
Request
curl -X DELETE https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id} \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
获取策略历史
返回某个策略的修订记录。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
响应数据
- Name
- data
- Type
- PolicyRevision[]
- Description
策略修订数组,包含字段级
changes(如有)。
Request
curl -X GET https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id}/history \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
获取策略钱包
返回策略及其当前的 wallet_ids。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
响应数据
- Name
- data
- Type
- Policy
- Description
策略对象。
Request
curl -X GET https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id}/wallets \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
更新策略钱包
替换策略的钱包目标列表。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
请求体参数
- Name
- wallet_ids
- Type
- string[]
- Description
可选。最多 500 个钱包 UUID。传入空数组表示针对所有钱包。
Request
curl -X PUT https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id}/wallets \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature==" \
-H "Content-Type: application/json" \
-d '{ "wallet_ids": ["e0851607-417a-475a-b399-5f3aa262b81d"] }'
创建策略规则
在已有策略下创建一条规则。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- policy_id
- Type
- string
- Description
Policy UUID.
请求体参数
- Name
- id
- Type
- string
- Description
可选的规则 UUID。
- Name
- trigger_action
- Type
- string
- Required
- required
- Description
取值为
withdrawal.create、web3.transfer、web3.contract_call或web3.sign_message之一。
- Name
- condition
- Type
- string
- Required
- required
- Description
1 到 4000 个字符。
- Name
- effect
- Type
- string
- Required
- required
- Description
取值为
ALLOW或DENY之一。web3.sign_message规则仅支持拒绝。
- Name
- description
- Type
- string
- Description
可选。最多 500 个字符。
- Name
- is_enabled
- Type
- boolean
- Description
可选。默认为
true。
Request
curl -X POST https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/{policy_id}/rules \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature==" \
-H "Content-Type: application/json" \
-d '{
"trigger_action": "web3.contract_call",
"condition": "resource.gas_limit > 100000",
"effect": "DENY",
"is_enabled": true
}'
更新策略规则
更新可变的规则字段。触发操作不可变,如需更改,请删除并重新创建该规则。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- rule_id
- Type
- string
- Description
Rule UUID.
请求体参数
- Name
- condition
- Type
- string
- Description
可选。1 到 4000 个字符。
- Name
- effect
- Type
- string
- Description
可选。取值为
ALLOW或DENY之一。
- Name
- description
- Type
- string
- Description
可选。最多 500 个字符。
- Name
- is_enabled
- Type
- boolean
- Description
可选。
Request
curl -X PUT https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/rules/{rule_id} \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature==" \
-H "Content-Type: application/json" \
-d '{
"condition": "resource.gas_limit > 150000",
"is_enabled": true
}'
删除策略规则
删除一条策略规则,或创建一个等待审批的规则删除变更。
路径参数
- Name
- workspace_id
- Type
- string
- Description
Workspace UUID.
- Name
- rule_id
- Type
- string
- Description
Rule UUID.
响应数据
- Name
- data
- Type
- Mutation response
- Description
规则变更响应。
Request
curl -X DELETE https://api.fystack.io/api/v1/workspaces/{workspace_id}/policies/rules/{rule_id} \
-H "ACCESS-API-KEY: your_api_key" \
-H "ACCESS-TIMESTAMP: 1667836889" \
-H "ACCESS-SIGN: YourBase64EncodedSignature=="
设计模式
将 DENY 规则用于硬性控制:制裁名单、未知收款方、新的地址簿条目、预计流出量限额、未知代币、无限额 permit 或高风险合约方法。
谨慎地缩小 ALLOW 规则的范围。匹配的 ALLOW 会跳过审批,因此条件应当精确:低 USD 金额、受信任的发起方、已知的目标钱包、已知的网络,以及经过地址存在时长检查的已知收款方,或已知的合约和方法。
为每条 ALLOW 搭配一个 DENY 上限,例如 wallet.projected_outflow_24h 或 workspace.initiator_projected_outflow_24h。由于 DENY 始终优先,这个上限同样会限制自动批准的路径。
保持策略集精简且明确。覆盖整个工作区的宽泛策略适合作为基线控制;当热钱包、资金库钱包或客户钱包有不同的风险阈值时,以钱包为作用域的策略更为合适。
完整示例请参阅策略模板。