Políticas

Las políticas de Fystack son salvaguardas programables para acciones sensibles de billeteras. Una política se aplica a un espacio de trabajo, opcionalmente se limita a billeteras específicas y contiene reglas que evalúan una expresión sobre un payload estructurado de la acción.

Las reglas se ejecutan para cuatro acciones:

  • Name
    withdrawal.create
    Type
    trigger_action
    Description

    Se evalúa antes de crear un retiro. Un DENY bloquea la solicitud. Un ALLOW coincidente omite la aprobación de la transacción y permite que el retiro pase a la firma.

  • Name
    web3.transfer
    Type
    trigger_action
    Description

    Se evalúa cuando se envía una transferencia de moneda nativa o ERC-20 a través de la API de transacciones sin procesar de Web3. Usa los mismos campos withdrawal.* que withdrawal.create, por lo que una condición se lee igual en ambos disparadores. Los campos de velocidad no están disponibles, porque estas transferencias no son retiros. Las transferencias ERC-20 también se evalúan como web3.contract_call.

  • Name
    web3.contract_call
    Type
    trigger_action
    Description

    Se evalúa antes de que las llamadas a contratos EVM y las transferencias de tokens ERC-20 se envíen a la firma. Un DENY registra la actividad como denied_by_policy. Un ALLOW coincidente omite la aprobación de la transacción y continúa con la firma.

  • Name
    web3.sign_message
    Type
    trigger_action
    Description

    Se evalúa cuando se solicita a una billetera firmar un mensaje con personal_sign, eth_sign o eth_signTypedData_v4. Solo admite denegación: un mensaje firmado siempre pasa por aprobación.

El esquema de políticas se genera a partir del esquema de acciones del backend en Apex. Usa Obtener el esquema de políticas al crear constructores de UI o para validar dinámicamente la disponibilidad de campos. Para reglas listas para usar, consulta Plantillas de políticas.


Estructura de una política

Una política es el contenedor. Una regla es la unidad ejecutable.

{
  "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

    El grupo de aprobación que revisa la creación, edición y eliminación de políticas, así como los cambios en las reglas.

  • Name
    wallet_ids
    Type
    string[]
    Description

    Billeteras a las que se aplica esta política. Un array vacío significa todas las billeteras del espacio de trabajo.

  • Name
    rules
    Type
    array
    Description

    Hasta 50 reglas. Cada regla tiene trigger_action, condition, effect, description opcional e is_enabled opcional.

Estados de una política

  • Name
    pending
    Type
    status
    Description

    Creada pero aún no aprobada. Las políticas pendientes no se evalúan.

  • Name
    active
    Type
    status
    Description

    Aprobada y en vigor. El evaluador solo carga las políticas activas.

  • Name
    inactive
    Type
    status
    Description

    Deshabilitada y no se evalúa.

  • Name
    rejected
    Type
    status
    Description

    Rechazada durante la aprobación y no se evalúa.


Evaluación de políticas

Para cada solicitud protegida, Fystack carga las políticas activas del espacio de trabajo, compila las reglas habilitadas, filtra las coincidencias por acción y por billeteras objetivo, y luego resuelve el resultado:

  1. Si alguna regla coincidente tiene effect: "DENY", la acción se bloquea.
  2. De lo contrario, si alguna regla coincidente tiene effect: "ALLOW", la acción continúa y se omite la aprobación de la transacción.
  3. De lo contrario, ninguna regla de política coincidió. La acción continúa por el flujo de aprobación normal.

DENY siempre prevalece sobre ALLOW, por lo que el orden de las reglas nunca cambia el resultado. Dentro del efecto ganador, la primera coincidencia en orden de declaración se usa para la atribución, de modo que la API puede devolver un rule_id estable y el motivo de la política.

No existe un efecto separado de "requerir aprobación". La aprobación es el comportamiento predeterminado para cualquier acción que no coincida con ninguna regla ALLOW.

La evaluación es fail-closed. Los fallos de caché, base de datos, compilación o evaluación en tiempo de ejecución deniegan la acción. Cada evaluación tiene un timeout de 100 ms.

Alcance y caché

Las políticas tienen alcance por espacio de trabajo. Apex almacena en caché un paquete de políticas compilado por espacio de trabajo y lo invalida tras aprobaciones o rechazos de políticas y cambios en las billeteras objetivo. El filtrado por billetera ocurre durante la evaluación, por lo que un mismo paquete puede servir a todas las billeteras de ese espacio de trabajo.


Condiciones

condition es una expresión que debe devolver un booleano. Haz referencia a los campos por sección y nombre de campo, por ejemplo principal.role, withdrawal.value_usd, wallet.purpose o resource.method_selector.

Usa los operadores habituales booleanos, de comparación y de pertenencia:

&&  ||  !  ==  !=  >  >=  <  <=  in

in comprueba la pertenencia a una lista literal o a un campo de tipo lista, por ejemplo principal.api_key_id in ["<api_key_id>"] o "0x…" in resource.permit_tokens.

Ejemplos:

  • Name
    Denegar retiros grandes a direcciones no incluidas en la lista blanca
    Type
    DENY
    Description

    withdrawal.value_usd > 10000 && !withdrawal.is_whitelisted

  • Name
    Limitar cada billetera a $100,000 por día
    Type
    DENY
    Description

    wallet.projected_outflow_24h > 100000

  • Name
    Mantener los fondos de custodia dentro del espacio de trabajo
    Type
    DENY
    Description

    wallet.purpose == "custody" && !withdrawal.destination_is_internal

  • Name
    Omitir la aprobación para una clave de API de pagos
    Type
    ALLOW
    Description

    principal.initiator_type == "api_key" && principal.api_key_id in ["<api_key_id>"] && withdrawal.value_usd < 1000

  • Name
    Omitir la aprobación para entradas antiguas de la libreta de direcciones
    Type
    ALLOW
    Description

    withdrawal.is_whitelisted && withdrawal.address_age_sec >= 86400 && withdrawal.value_usd <= 1000

  • Name
    Denegar retiros de alto valor en fin de semana
    Type
    DENY
    Description

    (context.day_of_week == "Saturday" || context.day_of_week == "Sunday") && withdrawal.value_usd > 25000

  • Name
    Denegar transferencias ERC-20 con gas elevado
    Type
    DENY
    Description

    resource.method_selector == "0xa9059cbb" && resource.gas_limit > 100000

  • Name
    Denegar permits de tokens ilimitados
    Type
    DENY
    Description

    resource.is_permit && resource.permit_amount_is_unlimited

resource.decoded_args es dinámico. Protege los campos dinámicos con has(...) antes de leerlos, por ejemplo has(resource.decoded_args.to) && resource.decoded_args.to == "0x000000000000000000000000000000000000dead".

Campos de referencia

Los campos marcados con ref en el esquema contienen el ID o código de otra entidad del espacio de trabajo: workspace_user, api_key, wallet, address_book, network o asset_symbol. Los constructores de condiciones deben mostrar un selector para estos campos.

Cuando se guarda una regla, Fystack comprueba que cada ID referenciado pertenezca a tu espacio de trabajo. Si una entidad se elimina o revoca más adelante, la regla conserva el ID y solo puede coincidir con menos casos, nunca con más.


Esquema de acciones

El esquema de acciones define los campos disponibles dentro de una condición. Los campos marcados como deprecated se siguen evaluando en las reglas existentes, pero no deben usarse en reglas nuevas.

Campos comunes

Todas las acciones disparadoras exponen los siguientes campos.

  • Name
    principal.user_id
    Type
    string · ref workspace_user
    Description

    ID del miembro del espacio de trabajo que inició la acción. Vacío cuando el iniciador es una clave de API.

  • Name
    principal.role
    Type
    string
    Description

    Rol en el espacio de trabajo. Uno de owner, admin, signer, proposer o viewer.

  • Name
    principal.initiator_type
    Type
    string
    Description

    user para una sesión web, o api_key para una clave de API.

  • Name
    principal.api_key_id
    Type
    string · ref api_key
    Description

    ID de la clave de API que inició la acción. Vacío para sesiones web, así que combínalo con principal.initiator_type.

  • Name
    principal.user_email
    Type
    string · deprecated
    Description

    Email del usuario iniciador. Usa principal.user_id en su lugar, porque un email puede cambiar.

  • Name
    wallet.id
    Type
    string · ref wallet
    Description

    ID de la billetera de origen. Úsalo para reglas que apuntan a billeteras específicas dentro de una política.

  • Name
    wallet.purpose
    Type
    string
    Description

    Propósito de la billetera de origen. Uno de general, custody, payment, user, one_time_use, gas_tank o deployment.

  • Name
    wallet.type
    Type
    string
    Description

    Tipo de la billetera de origen. standard o mpc.

  • Name
    context.hour
    Type
    integer
    Description

    Hora UTC de la evaluación, de 0 a 23.

  • Name
    context.day_of_week
    Type
    string
    Description

    Nombre del día de la semana en UTC, por ejemplo Monday o Saturday.

Campos de retiro

Disponibles en withdrawal.create y web3.transfer.

  • Name
    withdrawal.amount
    Type
    number
    Description

    Cantidad solicitada del activo.

  • Name
    withdrawal.value_usd
    Type
    number
    Description

    Valor solicitado en USD.

  • Name
    withdrawal.asset_symbol
    Type
    string · ref asset_symbol
    Description

    Símbolo del activo, como USDT, ETH o BTC.

  • Name
    withdrawal.asset_is_native
    Type
    boolean
    Description

    Indica si el activo es el activo nativo de la red.

  • Name
    withdrawal.asset_is_known
    Type
    boolean
    Description

    Indica si el token está en el catálogo de activos de Fystack. Cuando es false, amount, value_usd y asset_symbol están vacíos, así que deniega explícitamente los tokens desconocidos si lo necesitas.

  • Name
    withdrawal.token_address
    Type
    string
    Description

    Dirección del contrato del token. Vacía para monedas nativas.

  • Name
    withdrawal.destination_address
    Type
    string
    Description

    Dirección del destinatario.

  • Name
    withdrawal.network_code
    Type
    string · ref network
    Description

    Internal network code.

  • Name
    withdrawal.is_whitelisted
    Type
    boolean
    Description

    Indica si la dirección de destino está en alguna entrada de la libreta de direcciones del espacio de trabajo.

  • Name
    withdrawal.address_book_id
    Type
    string · ref address_book
    Description

    La entrada de la libreta de direcciones que contiene la dirección de destino. Una entrada abarca todas sus direcciones, por lo que funciona como una lista con nombre.

  • Name
    withdrawal.address_age_sec
    Type
    number
    Description

    Segundos transcurridos desde que la dirección de destino se agregó a su entrada de la libreta de direcciones. Úsalo para reglas de periodo de espera sobre destinatarios agregados recientemente.

  • Name
    withdrawal.destination_is_internal
    Type
    boolean
    Description

    Indica si el destino es otra billetera del mismo espacio de trabajo.

  • Name
    withdrawal.destination_wallet_id
    Type
    string · ref wallet
    Description

    La billetera de destino cuando el destino es interno.

Campos de velocidad de retiros

Disponibles solo en withdrawal.create. Todos los valores están en USD salvo que se indique lo contrario.

  • Name
    wallet.outflow_1h / outflow_6h / outflow_24h
    Type
    number
    Description

    Salida de fondos realizada de la billetera de origen en las últimas 1, 6 o 24 horas.

  • Name
    wallet.withdrawal_count_1h
    Type
    integer
    Description

    Intentos de retiro desde la billetera de origen en la última hora.

  • Name
    wallet.pending_outflow
    Type
    number
    Description

    Valor de los retiros de la billetera de origen que aún no se han ejecutado.

  • Name
    wallet.projected_outflow_24h
    Type
    number
    Description

    Salida realizada en 24 horas, más la salida pendiente, más el retiro que se está evaluando, para la billetera de origen.

  • Name
    wallet.asset_projected_outflow_24h
    Type
    number
    Description

    La misma proyección para la billetera de origen en unidades del activo retirado, por ejemplo como máximo 5 BTC por día.

  • Name
    workspace.outflow_1h / outflow_6h / outflow_24h
    Type
    number
    Description

    Salida de fondos realizada del espacio de trabajo en las últimas 1, 6 o 24 horas.

  • Name
    workspace.withdrawal_count_1h
    Type
    integer
    Description

    Intentos de retiro del espacio de trabajo en la última hora.

  • Name
    workspace.pending_outflow
    Type
    number
    Description

    Valor de los retiros del espacio de trabajo que aún no se han ejecutado.

  • Name
    workspace.projected_outflow_24h
    Type
    number
    Description

    Proyección del espacio de trabajo: salida realizada en 24 horas, más la salida pendiente, más el retiro que se está evaluando.

  • Name
    workspace.network_outflow_1h / network_outflow_6h / network_outflow_24h
    Type
    number
    Description

    Salida realizada del espacio de trabajo en la red actual durante las últimas 1, 6 o 24 horas.

  • Name
    workspace.network_withdrawal_count_1h
    Type
    integer
    Description

    Intentos de retiro del espacio de trabajo en la red actual en la última hora.

  • Name
    workspace.network_pending_outflow
    Type
    number
    Description

    Salida pendiente del espacio de trabajo en la red actual.

  • Name
    workspace.network_projected_outflow_24h
    Type
    number
    Description

    Proyección del espacio de trabajo en la red actual.

  • Name
    workspace.initiator_projected_outflow_24h
    Type
    number
    Description

    Proyección de los retiros creados por el mismo miembro o clave de API, en todo el espacio de trabajo.

Los campos de salida y de conteo son realizados: cuentan un retiro solo después de que alcanza un estado final ejecutado o exitoso. La salida pendiente cuenta los retiros que están esperando aprobación, en cola o fondeando gas, sin importar su antigüedad.

Cuando una regla activa usa un campo pendiente o proyectado, Fystack evalúa los retiros del espacio de trabajo de uno en uno, para que dos solicitudes concurrentes no puedan superar un límite al mismo tiempo. Una solicitud que espera más de 5 segundos su turno se rechaza con HTTP 429 y puede reintentarse.

Campos de web3.contract_call

  • Name
    resource.network_code
    Type
    string · ref network
    Description

    Internal network code.

  • Name
    resource.contract_address
    Type
    string
    Description

    Dirección del contrato en minúsculas, tomada del campo to de la transacción sin procesar.

  • Name
    resource.method_selector
    Type
    string
    Description

    Selector de 4 bytes en minúsculas, por ejemplo 0xa9059cbb.

  • Name
    resource.method_name
    Type
    string
    Description

    Nombre del método según los metadatos de la solicitud, si se proporciona.

  • Name
    resource.value_wei
    Type
    string
    Description

    Valor nativo enviado con la llamada, representado como string.

  • Name
    resource.gas_limit
    Type
    integer
    Description

    Límite de gas de la transacción sin procesar.

  • Name
    resource.decoded_args
    Type
    map
    Description

    Argumentos decodificados cuando Fystack reconoce la llamada. transfer de ERC-20 expone to y value.

Campos de web3.sign_message

  • Name
    resource.method
    Type
    string
    Description

    Método de firma. Uno de personal_sign, eth_sign o eth_signTypedData_v4.

  • Name
    resource.network_code
    Type
    string · ref network
    Description

    Internal network code.

  • Name
    resource.typed_data_primary_type
    Type
    string
    Description

    Tipo primario EIP-712, para mensajes de datos tipados.

  • Name
    resource.typed_data_domain_name
    Type
    string
    Description

    Nombre de dominio EIP-712, para mensajes de datos tipados.

  • Name
    resource.typed_data_verifying_contract
    Type
    string
    Description

    Contrato verificador EIP-712, para mensajes de datos tipados.

  • Name
    resource.is_permit
    Type
    boolean
    Description

    true para mensajes EIP-2612, DAI y Permit2, que permiten al spender mover tokens más adelante sin otra firma.

  • Name
    resource.permit_spender
    Type
    string
    Description

    La dirección que autoriza el permit.

  • Name
    resource.permit_tokens
    Type
    string[]
    Description

    Contratos de tokens que cubre el permit. Úsalo con in, por ejemplo "0x…" in resource.permit_tokens.

  • Name
    resource.permit_amount_is_unlimited
    Type
    boolean
    Description

    true para allowances de valor máximo (2159 o más, o un permit de DAI con allowed activado).

  • Name
    resource.permit_deadline
    Type
    integer
    Description

    Hora Unix en que expira el permit o su firma. 0 cuando el mensaje no tiene ninguna.


Ciclo de aprobación

Las operaciones de creación, actualización y eliminación de políticas requieren aprobación. La mutación crea una solicitud de aprobación de tipo policy y devuelve status: "pending_approval" con un approval_request_id. El cambio en la política se aplica solo después de que el grupo de aprobación alcanza el umbral.

Las operaciones de creación, actualización y eliminación de reglas siguen el mismo modelo cuando la política principal tiene un grupo de aprobación. La revisión pendiente almacena las diferencias a nivel de campo para auditoría y revisión.

Actualizar las billeteras objetivo mediante /wallets se aplica de inmediato tras la validación y la invalidación de la caché. Usa el endpoint de actualización de políticas cuando quieras que los cambios en las billeteras objetivo se revisen como parte de una revisión más amplia de la política.


Autenticación

Los endpoints de la API de políticas aceptan una solicitud firmada con clave de API o un token de acceso bearer.

  • Name
    ACCESS-API-KEY
    Type
    header
    Description

    UUID de la clave de API para solicitudes autenticadas con HMAC.

  • Name
    ACCESS-TIMESTAMP
    Type
    header
    Description

    Marca de tiempo UNIX en segundos usada para construir la firma HMAC.

  • Name
    ACCESS-SIGN
    Type
    header
    Description

    Firma HMAC codificada en Base64. Consulta Autenticación para ver el formato de firma.

  • Name
    Authorization
    Type
    header
    Description

    Token de acceso bearer para solicitudes de sesión de usuario.

Los endpoints de decisión de aprobación de políticas siguen siendo endpoints de sesión de usuario. Usa tokens de acceso bearer para aprobar o rechazar solicitudes de aprobación.

Envoltorio de respuesta

Las respuestas JSON exitosas usan el envoltorio estándar de Fystack.

  • Name
    success
    Type
    boolean
    Description

    true cuando la solicitud se realiza correctamente.

  • Name
    message
    Type
    string
    Description

    Mensaje de respuesta, normalmente success.

  • Name
    code
    Type
    integer
    Description

    Código numérico del resultado. Las respuestas exitosas usan 0.

  • Name
    data
    Type
    object | array | null
    Description

    Payload de respuesta específico del endpoint.

Los errores de validación usan el mismo envoltorio con success: false y un array errors.

Tipos de datos

Política

  • Name
    id
    Type
    string
    Description

    UUID de la política.

  • Name
    created_at
    Type
    string
    Description

    Marca de tiempo ISO de creación de la política.

  • Name
    updated_at
    Type
    string
    Description

    Marca de tiempo ISO de la última actualización de la política.

  • Name
    name
    Type
    string
    Description

    Nombre de la política. De 3 a 100 caracteres.

  • Name
    description
    Type
    string
    Description

    Descripción opcional. Hasta 500 caracteres.

  • Name
    status
    Type
    string
    Description

    Uno de pending, rejected, active o inactive.

  • Name
    version
    Type
    integer
    Description

    Número de versión de la política.

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    approval_group_id
    Type
    string | null
    Description

    UUID del grupo de aprobación asignado a la política.

  • Name
    wallet_ids
    Type
    string[]
    Description

    UUIDs de las billeteras objetivo. Un array vacío significa que la política se aplica a todas las billeteras del espacio de trabajo.

  • Name
    rules
    Type
    PolicyRule[]
    Description

    Presente en los endpoints que precargan las reglas.

  • Name
    approval_group
    Type
    object
    Description

    Presente en los endpoints que precargan el grupo de aprobación.

  • Name
    pending_approval_request
    Type
    object
    Description

    Presente cuando hay una solicitud de aprobación pendiente para la política.

PolicyRule

  • Name
    id
    Type
    string
    Description

    UUID de la regla.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política principal.

  • Name
    trigger_action
    Type
    string
    Description

    Uno de withdrawal.create, web3.transfer, web3.contract_call o web3.sign_message.

  • Name
    condition
    Type
    string
    Description

    Expresión de condición booleana. De 1 a 4000 caracteres.

  • Name
    effect
    Type
    string
    Description

    ALLOW o DENY.

  • Name
    description
    Type
    string
    Description

    Descripción opcional. Hasta 500 caracteres.

  • Name
    is_enabled
    Type
    boolean
    Description

    Indica si la regla está habilitada. Por defecto es true al crearla si se omite.

Respuesta de mutación

Los endpoints de mutación de políticas y reglas devuelven un payload de mutación en data.

  • Name
    status
    Type
    string
    Description

    Uno de applied, pending_approval o deleted, según la operación.

  • Name
    policy
    Type
    Policy
    Description

    Lo devuelven los endpoints de mutación de políticas cuando corresponde.

  • Name
    rule
    Type
    PolicyRule
    Description

    Lo devuelven los endpoints de mutación de reglas cuando corresponde.

  • Name
    approval_request_id
    Type
    string
    Description

    Se devuelve cuando la mutación está esperando aprobación.

Obtener el esquema de políticas

GET
/policy/schema

Devuelve los campos a los que puede hacer referencia una condición, agrupados por trigger_action y sección. Usa este endpoint para constructores de condiciones y vistas previas del lado del cliente.

Cada campo tiene name y type. Claves opcionales:

  • Name
    enum
    Type
    string[]
    Description

    Los valores permitidos para el campo.

  • Name
    ref
    Type
    string
    Description

    La entidad a la que hace referencia el campo. Muestra un selector para ella. Consulta Campos de referencia.

  • Name
    deprecated
    Type
    boolean
    Description

    Se sigue evaluando en las reglas existentes. Ocúltalo en los constructores de reglas nuevas.

Request

GET
/policy/schema
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 ..." ]
    }
  }
}

Validar una regla

POST
/workspaces/{workspace_id}/policies/rules/validate

Valida el cuerpo de una regla sin crear ni actualizar ninguna regla.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

Parámetros del cuerpo

  • Name
    trigger_action
    Type
    string
    Required
    required
    Description

    Uno de withdrawal.create, web3.transfer, web3.contract_call o web3.sign_message.

  • Name
    condition
    Type
    string
    Required
    required
    Description

    De 1 a 4000 caracteres. Debe compilar a una expresión booleana.

  • Name
    effect
    Type
    string
    Required
    required
    Description

    ALLOW o DENY. Las reglas web3.sign_message solo admiten denegación.

Datos de respuesta

  • Name
    valid
    Type
    boolean
    Description

    true cuando el cuerpo de la regla es válido.

Request

POST
/workspaces/{workspace_id}/policies/rules/validate
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 }
}

Crear una política

POST
/workspaces/{workspace_id}/policies

Crea una mutación de política.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

Parámetros del cuerpo

  • Name
    name
    Type
    string
    Required
    required
    Description

    De 3 a 100 caracteres.

  • Name
    description
    Type
    string
    Description

    Opcional. Hasta 500 caracteres.

  • Name
    approval_group_id
    Type
    string
    Required
    required
    Description

    UUID del grupo de aprobación.

  • Name
    wallet_ids
    Type
    string[]
    Description

    Opcional. Hasta 500 UUIDs de billeteras.

  • Name
    rules
    Type
    PolicyRuleCreate[]
    Description

    Opcional. Hasta 50 reglas.

Request

POST
/workspaces/{workspace_id}/policies
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": []
    }
  }
}

Listar políticas

GET
/workspaces/{workspace_id}/policies

Devuelve las políticas de un espacio de trabajo.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

Parámetros de consulta

  • Name
    status
    Type
    string
    Description

    Opcional. Uno de pending, rejected, active o inactive.

  • Name
    limit
    Type
    integer
    Description

    Opcional. Máximo 1000.

  • Name
    offset
    Type
    integer
    Description

    Opcional. Máximo 100000.

Datos de respuesta

  • Name
    data
    Type
    Policy[]
    Description

    Array de objetos de política.

Request

GET
/workspaces/{workspace_id}/policies
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=="

Obtener una política

GET
/workspaces/{workspace_id}/policies/{policy_id}

Devuelve una sola política.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Datos de respuesta

  • Name
    data
    Type
    Policy
    Description

    Objeto de política, que incluye las reglas, el grupo de aprobación y la solicitud de aprobación pendiente, si existe.

Request

GET
/workspaces/{workspace_id}/policies/{policy_id}
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=="

Actualizar una política

PUT
/workspaces/{workspace_id}/policies/{policy_id}

Actualiza los campos de la política.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Parámetros del cuerpo

  • Name
    name
    Type
    string
    Description

    Opcional. De 3 a 100 caracteres.

  • Name
    description
    Type
    string
    Description

    Opcional. Hasta 500 caracteres.

  • Name
    approval_group_id
    Type
    string
    Description

    UUID opcional del grupo de aprobación.

  • Name
    wallet_ids
    Type
    string[]
    Description

    Opcional. Hasta 500 UUIDs de billeteras. Envía un array vacío para aplicarla a todas las billeteras.

  • Name
    rules
    Type
    PolicyRuleCreate[]
    Description

    Opcional. Si se incluye, reemplaza el conjunto completo de reglas. Envía un array vacío para eliminar todas las reglas.

Request

PUT
/workspaces/{workspace_id}/policies/{policy_id}
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"]
  }'

Eliminar una política

DELETE
/workspaces/{workspace_id}/policies/{policy_id}

Elimina una política o crea una mutación de eliminación que espera aprobación.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Datos de respuesta

  • Name
    data
    Type
    Mutation response
    Description

    Respuesta de mutación de la política.

Request

DELETE
/workspaces/{workspace_id}/policies/{policy_id}
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=="

Obtener el historial de una política

GET
/workspaces/{workspace_id}/policies/{policy_id}/history

Devuelve las revisiones de una política.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Datos de respuesta

  • Name
    data
    Type
    PolicyRevision[]
    Description

    Array de revisiones de la política, que incluye los changes a nivel de campo cuando existen.

Request

GET
/workspaces/{workspace_id}/policies/{policy_id}/history
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=="

Obtener las billeteras de una política

GET
/workspaces/{workspace_id}/policies/{policy_id}/wallets

Devuelve la política con sus wallet_ids actuales.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Datos de respuesta

  • Name
    data
    Type
    Policy
    Description

    Objeto de política.

Request

GET
/workspaces/{workspace_id}/policies/{policy_id}/wallets
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=="

Actualizar las billeteras de una política

PUT
/workspaces/{workspace_id}/policies/{policy_id}/wallets

Reemplaza la lista de billeteras objetivo de una política.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Parámetros del cuerpo

  • Name
    wallet_ids
    Type
    string[]
    Description

    Opcional. Hasta 500 UUIDs de billeteras. Envía un array vacío para aplicarla a todas las billeteras.

Request

PUT
/workspaces/{workspace_id}/policies/{policy_id}/wallets
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"] }'

Crear una regla de política

POST
/workspaces/{workspace_id}/policies/{policy_id}/rules

Crea una regla dentro de una política existente.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    policy_id
    Type
    string
    Description

    UUID de la política.

Parámetros del cuerpo

  • Name
    id
    Type
    string
    Description

    UUID opcional de la regla.

  • Name
    trigger_action
    Type
    string
    Required
    required
    Description

    Uno de withdrawal.create, web3.transfer, web3.contract_call o web3.sign_message.

  • Name
    condition
    Type
    string
    Required
    required
    Description

    De 1 a 4000 caracteres.

  • Name
    effect
    Type
    string
    Required
    required
    Description

    ALLOW o DENY. Las reglas web3.sign_message solo admiten denegación.

  • Name
    description
    Type
    string
    Description

    Opcional. Hasta 500 caracteres.

  • Name
    is_enabled
    Type
    boolean
    Description

    Opcional. Por defecto es true.

Request

POST
/workspaces/{workspace_id}/policies/{policy_id}/rules
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
  }'

Actualizar una regla de política

PUT
/workspaces/{workspace_id}/policies/rules/{rule_id}

Actualiza los campos modificables de la regla. La acción disparadora es inmutable, así que elimina y vuelve a crear la regla para cambiarla.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    rule_id
    Type
    string
    Description

    UUID de la regla.

Parámetros del cuerpo

  • Name
    condition
    Type
    string
    Description

    Opcional. De 1 a 4000 caracteres.

  • Name
    effect
    Type
    string
    Description

    Opcional. ALLOW o DENY.

  • Name
    description
    Type
    string
    Description

    Opcional. Hasta 500 caracteres.

  • Name
    is_enabled
    Type
    boolean
    Description

    Opcional.

Request

PUT
/workspaces/{workspace_id}/policies/rules/{rule_id}
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
  }'

Eliminar una regla de política

DELETE
/workspaces/{workspace_id}/policies/rules/{rule_id}

Elimina una regla de política o crea una mutación de eliminación de regla que espera aprobación.

Parámetros de ruta

  • Name
    workspace_id
    Type
    string
    Description

    UUID del espacio de trabajo.

  • Name
    rule_id
    Type
    string
    Description

    UUID de la regla.

Datos de respuesta

  • Name
    data
    Type
    Mutation response
    Description

    Respuesta de mutación de la regla.

Request

DELETE
/workspaces/{workspace_id}/policies/rules/{rule_id}
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=="

Patrones de diseño

Usa reglas DENY para controles estrictos: listas de sanciones, destinatarios desconocidos, entradas nuevas en la libreta de direcciones, límites de salida proyectada, tokens desconocidos, permits ilimitados o métodos de contrato de alto riesgo.

Usa reglas ALLOW de forma acotada. Un ALLOW coincidente omite la aprobación, así que las condiciones deben ser precisas: bajo valor en USD, iniciador de confianza, billetera objetivo conocida, red conocida y un destinatario conocido con verificación de antigüedad de la dirección, o un contrato y método conocidos.

Combina cada ALLOW con un techo DENY, como wallet.projected_outflow_24h o workspace.initiator_projected_outflow_24h. Como DENY siempre prevalece, el techo también limita la ruta de aprobación automática.

Mantén los conjuntos de políticas pequeños y explícitos. Las políticas amplias a nivel de espacio de trabajo son útiles para controles básicos, mientras que las políticas por billetera son mejores cuando una hot wallet, una billetera de tesorería o una billetera de cliente tiene umbrales de riesgo distintos.

Consulta Plantillas de políticas para ver ejemplos completos.