Dfns API Documentation
  • 👋Welcome
  • Getting Started
    • Onboarding to Dfns
    • Dfns Environments
    • Core API Objects
    • Supported Assets
    • Postman
    • Dfns SDKs
    • Dashboard Videos
  • API Docs
    • Introduction
    • Authentication
      • Delegated Authentication
        • Delegated Registration
        • Delegated Registration Restart
        • Delegated Login
      • User Action Signing
        • Create User Action Signature Challenge
        • Create User Action Signature
      • Registration
        • Create User Registration Challenge
        • Complete User Registration
        • Complete End User Registration with Wallets
        • Resend Registration Code
        • Social Registration
      • Login
        • Create User Login Challenge
        • Complete User Login
        • Social Login
        • Logout
        • Send Login Code
      • Users
        • List Users
        • Create User
        • Get User
        • Activate User
        • Deactivate User
        • Archive User
      • Service Accounts
        • List Service Accounts
        • Create Service Account
        • Get Service Account
        • Update Service Account
        • Activate Service Account
        • Deactivate Service Account
        • Archive Service Account
      • Applications
        • List Applications
        • Create Application
        • Create Server-Signed Application
        • Get Application
        • Update Application
        • Activate Application
        • Deactivate Application
        • Archive Application
      • Personal Access Tokens
        • List Personal Access Tokens
        • Create Personal Access Token
        • Get Personal Access Token
        • Update Personal Access Token
        • Activate Personal Access Token
        • Deactivate Personal Access Token
        • Archive Personal Access Token
      • Credentials
        • Credentials Overview
        • API Reference
          • Create Credential Code
          • Create Credential Challenge
          • Create Credential Challenge With Code
          • Create Credential
          • Create Credential With Code
          • Deactivate Credential
          • Activate Credential
          • List Credentials
      • Recovery
        • Send Recovery Code Email
        • Create Recovery Challenge
        • Create Delegated Recovery Challenge
        • Recover User
    • Wallets
      • Create Wallet
      • Update Wallet
      • Delete Wallet
      • [deprecated] Delegate Wallet
      • Get Wallet by ID
      • List Wallets
      • Get Wallet Assets
      • Get Wallet NFTs
      • Get Wallet History
      • Tag Wallet
      • Untag Wallet
      • Transfer Asset
      • Get Transfer Request by ID
      • List Transfer Requests
      • Sign and Broadcast Transaction
        • Algorand
        • Aptos
        • Bitcoin / Litecoin
        • Canton
        • Cardano
        • EVM
        • Solana
        • Stellar
        • Tezos
        • TRON
        • XRP Ledger (Ripple)
      • Get Transaction Request by ID
      • List Transaction Requests
      • [deprecated] Generate Signature
      • Advanced Wallet APIs
        • Import Wallet
        • [deprecated] Export Wallet
    • Fee Sponsors
      • Create Fee Sponsor
      • Get Fee Sponsor
      • List Fee Sponsors
      • Activate Fee Sponsor
      • Deactivate Fee Sponsor
      • Delete Fee Sponsor
      • List Sponsored Fees
    • Keys
      • Create Key
      • Update Key
      • Delete Key
      • Delegate Key
      • Get Key by ID
      • List Keys
      • Generate Signature
        • Algorand
        • Aptos
        • Bitcoin / Litecoin
        • Cardano
        • Cosmos Appchain
        • EVM
        • Solana
        • Stellar
        • Substrate (Polkadot)
        • Tezos
        • TON
        • TRON
        • XRP Ledger (Ripple)
      • Get Signature Request by ID
      • List Signature Requests
      • Advanced Key APIs
        • Import Key
        • Export Key
        • Deterministic Derivation
    • Networks
      • Estimate fees
      • Read Contract
      • Validators
        • Create Validator
        • List Validators
    • Policy Engine
      • Policies Overview
      • API Reference
        • Create Policy
        • Get Policy
        • List Policies
        • Update Policy
        • Archive Policy
        • Get Approval
        • List Approvals
        • Create Approval Decision
    • Permissions
      • Permissions Overview
      • API Reference
        • Get Permission
        • List Permissions
        • Create Permission
        • Update Permission
        • Archive Permission
        • Assign Permission
        • Revoke Permission
        • List Permission Assignments
    • Webhooks
      • Create Webhook
      • Get Webhook
      • List Webhooks
      • Update Webhook
      • Delete Webhook
      • Ping Webhook
      • Get Webhook Event
      • List Webhook Events
    • Dfns Change Log
    • API Errors
  • Integrations
    • Exchanges
      • Kraken
      • Binance
      • Coinbase Prime
      • API Reference
        • Create Exchange
        • List Exchanges
        • Get Exchange
        • Delete Exchange
        • List Exchange Accounts
        • List Exchange Account Assets
        • Create Exchange Deposit
        • Create Exchange Withdrawal
    • AML / KYT
      • Chainalysis
    • Staking
      • API Reference
        • Create Stake
        • Create Stake Action
        • List Stakes
        • List Stake Actions
        • get Rewards
    • Fiat On/Off-Ramps
    • Account Abstraction on EVMs
  • Advanced Topics
    • Authentication
      • API Authentication
      • Request Headers
      • Credentials
        • Generate a Key Pair
        • User Credentials
        • Access Token Credentials
        • Storing WebAuthn Credentials in Password Managers
      • Request Signing
      • API objects
    • Delegated Signing
    • API Idempotency
    • FAQ
  • Guides
    • Passkey Settings - Migration guide
    • Keys & Multichain - Migration Guide
Powered by GitBook
On this page
  • Activities
  • Wallets:Sign activity
  • Wallets:IncomingTransaction activity
  • Permissions:Modify activity
  • Permissions:Assign activity
  • Policies:Modify activity
  • Policy Rules
  • AlwaysTrigger policy rule
  • TransactionAmountLimit policy rule
  • TransactionAmountVelocity policy rule
  • TransactionCountVelocity policy rule
  • TransactionRecipientWhitelist policy rule
  • ChainalysisTransactionPrescreening policy rule
  • ChainalysisTransactionScreening policy rule
  • Policy Action
  • Block policy action
  • RequestApproval policy action
  • NoAction policy action
  • Policy Filters
  • Filters for "Wallets:Sign" activity
  • Filters for "Policies:Modify" activity
  • Filters for "Permissions:Modify" activity
  • Filters for "Permissions:Assign" activity
  • Approval
  1. API Docs
  2. Policy Engine

Policies Overview

Last updated 25 days ago

A Policy acts as a "gate" for a given activity in Dfns system, which enforces a set of rules before the activity is executed. If triggered, a policy can either block the activity or launch an approval process before finalizing the activity.

A Policy is defined by:

  • an : the type of activity that this policy should gate.

  • a : defines the rule being evaluated to know whether the policy should "activate" (aka "trigger") or not for a given activity happening in the system.

  • an : after rule was evaluated, if the policy is triggered, the action defines what action is taken as a consequence.

  • optional : these can be used to reduce the scope upon which the policy applies.

Once evaluated for a given activity, a policy is either Skipped if the rule did not apply or is triggered executing the associated action. If the action is RequestApproval, an process is initiated.


Activities

"Activity" is a generic term describing some activity in the Dfns system. Supported activity kinds are: , , , .

Wallets:Sign activity

A "Wallets:Sign" activity represents any activity which involves signing with a wallet. Currently, in our API, these can be:

  • a Transfer Request (created using the endpoint )

  • a Transaction Request (created using the endpoint )

  • a Signature Request (created using the endpoint )

Wallets:IncomingTransaction activity

Permissions:Modify activity

A "Permissions:Modify" activity represents any activity which involves updating or archiving a permission. These activities are Permission change requests, created as a result of calling either:

Permissions:Assign activity

A "Permissions:Assign" activity represents any activity which involves assigning a permission (or revoking it, aka "deleting a permission assignment"). These activities are Assignment change requests, created as a result of calling either:

Policies:Modify activity

A "Policies:Modify" activity represents any activity which involves updating or archiving a policy. These activities are Policy change requests, created as a result of calling either:

Every policy requires a rule to be specified. Upon policy evaluation, the configuration specified in the rule will be used to determine whether the policy should trigger or not for a given activity.

By exposing controls on permissions and policies, Dfns enables the specification of an admin quorum to approve sensitive actions which could change system governance. Note Dfns does not expose a separate "admin quorum" concept like some of our competitors - we simply enable this use case as another configuration of the policy engine itself. This was chosen to promote flexibility as not every customer will have the same requirements around creating and managing admin quorums.


Policy Rules

The policy rule is what gets evaluated to determine whether a given activity will "activate" (aka "trigger") the policy, therefore applying the policy "Action", or whether it will skip it.

AlwaysTrigger policy rule

This rule can be used on a policy of any activityKind. It will always be triggered, meaning that if this rule is defined on a policy, the policy will always trigger the policy action, regardless of the activity details.

{
  "rule": {
    "kind": "AlwaysTrigger",
  }
}

TransactionAmountLimit policy rule

This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the wallet activity detected is transferring some value which amount is greater than a given limit.

If the fiat amount of the wallet activity cannot be evaluated for any reason (eg. market prices are not available, or eg. the amount cannot be inferred from a wallet signature request, etc.), by default the rule will trigger the policy (this is called "failing closed" and is generally considered a security best practice).

{
  "rule": {
    "kind": "TransactionAmountLimit",
    "configuration": {
      "limit": 1000,
      "currency": "USD",
    },
  }
}

Configuration

Property
Type
Description

limit*

Positive Integer

Amount limit in currency

currency*

String

Fiat currency, currently only USD

TransactionAmountVelocity policy rule

This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the cumulative amount transferred from a given wallet within a given timeframe is greater than a specified limit. The aggregate amount evaluated is based only on the wallet that triggered the policy.

If the fiat amount of any wallet activity in the given timeframe cannot be evaluated for any reason (eg. market prices are not available, or eg. the amount cannot be inferred from a wallet signature request, etc.), by default the rule will trigger the policy (ie. will fail closed).

{
  "rule": {
    "kind": "TransactionAmountVelocity",
    "configuration": {
      "limit": 1000,
      "currency": "USD",
      "timeframe": 60,
    },
  },
}

Configuration

Property
Type
Description

limit*

Positive Integer

Amount limit in currency

currency*

String

Fiat currency, currently only USD

timeframe*

Positive Integer

Time period in minutes. Minimum 1, Maximum 43,200.

TransactionCountVelocity policy rule

This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the number of wallet activities for a given wallet within a given timeframe, is greater than a specified limit. The aggregate number of transactions evaluated is based only on the wallet that triggered the policy.

{
  "rule": {
    "kind": "TransactionCountVelocity",
    "configuration": {
      "limit": 5,
      "timeframe": 60,
    },
  },
}

Configuration

Property
Type
Description

limit*

Positive Integer

Amount limit in currency

timeframe*

Positive Integer

Time period in minutes. Minimum 1, Maximum 43,200.

TransactionRecipientWhitelist policy rule

This rule can be used on a policy of activityKind = Wallets:Sign. It will trigger if the wallet activity transfers some value to a recipient and the destination address is NOT whitelisted.

Address comparison is case sensitive when evaluating the rule. For EVM addresses, make sure you use the canonical all lowercase address format, not the mixed-case checksum address format, in your policy rule configuration. Otherwise, the evaluation will fail and trigger the policy.

If the specified whitelisted address list is empty, it basically means "no addresses are whitelisted", so the rule will trigger for any wallet activities.

{
  "rule": {
    "kind": "TransactionRecipientWhitelist",
    "configuration": {
      "addresses": ["0x...1", "0x...2"],
    },
  }
}

Configuration

Property
Type
Description

addresses*

List of Positive Integer

Whitelisted recipient addresses

ChainalysisTransactionPrescreening policy rule

It's called "Pre"-screening, because the scanned transaction is not on chain yet, it's still a transaction attempt (before the transaction actually make it on chain).

{
  "rule": {
    "kind": "ChainalysisTransactionPrescreening",
    "configuration": {
      "alerts": {
        "alertLevel": "LOW",
        "categoryIds": []
      },
      "exposures": {
        "direct": {
          "categoryIds": []
        }
      },
      "addresses": {
        "categoryIds": []
      },
      "fallbackBehaviours": {
        "skipUnscreenableTransaction": false,
        "skipUnsupportedNetwork": false,
        "skipUnsupportedAsset": false,
        "skipChainalysisFailure": false
      }
    }
  }
}

Configuration

Property
Type
Description

alerts

.alertLevel*

string

alerts

.categoryIds*

list of integers

exposures

.direct

.categoryIds*

list of integers

addresses

.categoryIds*

list of integers

fallbackBehaviours

.skipUnscreenableTransaction*

boolean

Behaviour if the wallet activity is not screenable (eg. if it's a signature request of a hash). If true, a transaction which is "unscreenable" will just be skipped, and policy will not trigger

fallbackBehaviours.skipUnsupportedNetwork*

boolean

Behaviour if the wallet activity is on a network not supported by chainalysis, or not yet supported in the dfns-chainalysis integration. If true, an unsupported network will just be skipped, and policy will not trigger

fallbackBehaviours.skipUnsupportedAsset*

boolean

Behaviour if the wallet activity is with a asset not supported by chainalysis, or not yet supported in the dfns-chainalysis integration. If true, an unsupported asset will just be skipped, and policy will not trigger

fallbackBehaviours.skipChainalysisFailure*

boolean

Behaviour if any issue with Chainalysis calls (timeout, results took too long, rate limiting errors, any error). If true, will skip if any error happens

ChainalysisTransactionScreening policy rule

The shape of the rule is almost like the ChainalysisTransactionPrescreening rule, expect the the address property is not supported.

{
  "rule": {
    "kind": "ChainalysisTransactionPrescreening",
    "configuration": {
      "alerts": {
        "alertLevel": "LOW",
        "categoryIds": []
      },
      "exposures": {
        "direct": {
          "categoryIds": []
        }
      },
      "fallbackBehaviours": {
        "skipUnscreenableTransaction": false,
        "skipUnsupportedNetwork": false,
        "skipUnsupportedAsset": false,
        "skipChainalysisFailure": false
      }
    }
  }
}

Configuration

See the above configuration for rule ChainalysisTransactionPrescreening


Policy Action

Block policy action

This action means that the activity will be blocked if the policy is triggered.

{
  "action": {
    "kind": "Block"
  }
}

RequestApproval policy action

This action means that activity will first require an Approval process to be completed before it can be executed (or be aborted if someone rejects it during the approval process).

One or several groups of approvers need to be specified. These groups define who is allowed to approve / reject an activity.

The activity will only be executed if all approver groups reach their "quorum" of approvals. Otherwise, if any one user within any approver group rejects, then the activity is aborted and the call is not executed.

The example below shows a RequestApproval action, configured with one approval group requiring 2 approvals amongst three specific users.

{
  "action": {
    "kind": "RequestApproval",
    "autoRejectTimeout": 60, // minutes
    "approvalGroups": [
      {
        "name": "Admins",
        "quorum": 2, // only 2 approvers required in that group 
        "approvers": {
          "userId": {
            "in": ["us-...1", "us-...2", "us-...3"],
          }
        }
      }
    ],

  }
}
property
Type
Description

approvalGroups*

List of Object

List of approval groups. If multiple groups are defined, the approval is complete only when all groups have approved

approvalGroups[*]

.name

(Optional) String

Optional name of this group.

approvalGroups[*]

.quorum*

Positive Integer

The quorum is the number of approvals required in this group to reach group consensus. The activity is executed only if all groups reached their approval quorum.

approvalGroups[*]

.approvers*

Object

Defines all users that are allowed to approve in the group. If set to an empty object {}, it means that anyone within your organisation can be an approver. Otherwise, you can specify an exact list of allowed approvers, by adding their user IDs in this object: { userId: { in: [...] }}

autoRejectTimeout

(Optional) Positive Integer

Number of minutes after which, if the approval has not reach global consensus (all groups reached their consensus), the activity is automatically rejected. If not specified, the activity will never be rejected automatically (the approval process doesn't "expire" / "times out").

NoAction policy action

{
  "action": {
    "kind": "NoAction"
  }
}

Policy Filters

Policy filters can reduce the scope on which the policy applies. If no filters are specifies, the policy applies to all activities happening in your organisation (all activities of the kind defined by the policy activityKind).

For example, you can use filters to setup a policy for activities happening on specific wallets or on groups of wallets. Some examples include:

  • "All activities from wallets tagged 'group:treasury' must first be approved by the CEO

  • "All transfers from wallet ID 1 larger than $1k must first be approved by the CEO & the CFO"

  • "All transfers from wallets tagged 'accounting:freeze' must be blocked"

The filters that you can specify depend on the activityKind of your policy (activityKind)

Filters for "Wallets:Sign" activity

key
evaluator
Value

walletId

in

List of wallet IDs. If the activity is from a wallet within one of these IDs, the policy applies to this wallet.

walletTags

hasAny

List of tags. If the activity is from a wallet that has any of these tags, the policy will apply to this wallet.

walletTags

hasAll

List of tags. If the activity is from a wallet that has all of these tags, the policy will apply to this wallet.

Some examples:

  • The policy is scoped only to wallets with IDs wa-1 or wa-2:

{
  "filters": {
    "walletId": {
      "in": ["wa-1", "wa-2"]
    }
  }
}
  • The policy is scoped only to wallets tagged either "domain:accounting" or "sensitive":

{
  "filters": {
    "walletTags": {
      "hasAny": ["domain:accounting", "sensitive"]
    }
  }
}
  • The policy is scoped only to wallets tagged with both "domain:accounting" and "sensitive":

{
  "filters": {
    "walletTags": {
      "hasAll": ["domain:accounting", "sensitive"]
    }
  }
}
  • The policy is scoped only to wallets containing all these tags ("domain:accounting", "zone:asia") AND at least one of these tags ("security:high", "security:medium"):

{
  "filters": {
    "walletTags": {
      "hasAll": ["domain:accounting", "zone:asia"],
      "hasAny": ["security:high", "security:medium"]
    }
  }
}

Note the relationship between inclusion operators is always AND, not OR.

Filters for "Policies:Modify" activity

filter key
evaluator
Value

policyId

in

List of policy IDs. If the policy being modified is one of these IDs, the policy applies.

Some examples:

  • The policy is scoped only to policies with IDs plc-1 or plc-2

{
  "filters": {
    "policyId": {
      "in": ["plc-1", "plc-2"]
    }
  }
}

Filters for "Permissions:Modify" activity

filter key
evaluator
Value

permissionId

in

List of permission IDs. If the permission being modified is one of these IDs, the policy applies.

Some examples:

  • The policy is scoped only to permissions with IDs pm-1 or pm-2

{
  "filters": {
    "permissionId": {
      "in": ["pm-1", "pm-2"]
    }
  }
}

Filters for "Permissions:Assign" activity

filter key
evaluator
Value

permissionId

in

List of permission IDs. If the permission being assigned/revoked is one of these IDs, the policy applies.

Some examples:

  • The policy is scoped only to permissions with IDs pm-1 or pm-2

{
  "filters": {
    "permissionId": {
      "in": ["pm-1", "pm-2"]
    }
  }
}


Approval

When a policy is triggered and the action defined is RequestApproval, an Approval object is created containing:

  • details about the activity that triggered this approval flow

  • details on the different policy evaluations that happened for that activity and their result

  • details about the decisions given by each approvers

A user can only give his approval / rejection if he is defined inside one of the approval groups defined on the policies that triggered.

A given user can only approve or reject once. If multiple approval groups exist, a decision from a single user will count as a decision for any of the groups this user belongs to.

A rejection from any user of any groups immediately rejects an activity.

The initiator is not allowed to approve their activity, but can deny it if they need to cancel it.

Here's an Approval object example

{
  "id":"ap-...",
  "initiatorId":"us-...",
  "status":"Pending",
  "expirationDate":"2023-12-22T21:16:16.659Z",
  "dateCreated":"2023-12-22T20:56:16.662Z",
  "dateUpdated":"2023-12-22T20:56:16.662Z",
  "activity":{
    "kind": "Wallets:Sign",
    "transferRequest": { // the transfer request object from transfer endpoint
      "id": "xfr-...",
      ...
    },
  },
  "evaluatedPolicies":[
    {
      "policyId":"plc-...",
      "triggerStatus":"Triggered",
      "reason":"Number of transactions (2) is above limit (2)."
    },
    {
      "policyId":"plc-...",
      "triggerStatus":"Triggered",
      "reason":"Cumulative transfer amount (USD 20) is above limit (USD 2)."
    }
  ],
  "decisions":[
    {
      "userId":"us-...",
      "dateActioned":"2023-12-22T20:56:16.662Z",
      "value":"Approved"
    }
  ],
}

A "Wallets:IncomingTransaction" activity represents when our indexers detected an incoming transaction into a wallet. This activity kind has to be used with the rule kind "ChainalysisTransactionScreening" (see more on integration page), and the action kind "NoAction", meaning that no actual action will be taken as a result of the Chainalysis screening, other than notifying you through a webhook event if the policy is triggered. The reason for that, is that the incoming transaction is already on-chain, so the funds are already in the wallet, we cannot block that transfer on chain.

the endpoint

the endpoint

the endpoint

the endpoint

the endpoint

the endpoint

Supported Policy Rule kinds are:, , , , .

If the wallet activity is not a value transfer, or the transaction recipient cannot be inferred from the wallet activity (eg if you use ), by default the rule will trigger the policy (ie. fail closed).

This rule can only be used once the Chainalysis integration is activated from the Dfns dashboard settings. (see more on integration page)

This rule can be used on a policy of activityKind = Wallets:Sign. It's a rule based on KYT integration (Know-Your-Transaction). Upon transfer attempt, we will first register the transfer with Chainalysis (as a ), and fetch the screening results (alerts, exposures, addresses detected). Based on the results, and the configuration of this rule, the policy will be triggered.

Minimum alert level above which the rule should trigger, if any . Can be LOW, MEDIUM, HIGH, or SEVERE

List of Chainalysis category IDs (see ). If you leave this list empty, alerts of any category will trigger the rule. Otherwise, if you only want the rule to trigger on specific categories, you can specify some in the list.

List of Chainalysis category IDs (see ). If you leave this list empty, a of any category detected by chainalysis will trigger the rule. Otherwise, if you only want the rule to trigger on specific categories, you can specify some in the list.

List of Chainalysis category IDs (see ). If you leave this list empty, an of any category identified by chainalysis will trigger the rule. Otherwise, if you only want the rule to trigger on specific categories, you can specify some in the list.

This rule can only be used once the Chainalysis integration is activated from the Dfns dashboard settings (see more on integration page)

This rule can be used on a policy of activityKind = Wallets:IncomingTransaction, and with the action kind NoAction. It's a rule based on Chainalysis KYT integration (Know-Your-Transaction). Upon an incoming transaction detectedby our indexers, we will , and fetch the results of the analysis (alerts & exposures detected). Based on the results, and the configuration of this rule, the policy will be triggered.

An action specifies what should happen if a policy rule is triggered. Supported action kinds are: and.

This action kind means that nothing will happen after policy rule evaluation. It's meant to be used with policy rules "ChainalysisTransactionPrescreening" or "ChainalysisTransactionScreening". This action is for when you just want the KYT analysis rule to be run, and then if triggered, those result returned in a policy.triggered .

When a new Approval object is created and an approval process is required, a is emitted (event kind "policy.approval.pending"). You can subscribe to it to react to this event, eg. send notifications to the users that need to give their approval.

The Approval object can be queried using the approvalId returned from the endpoint that triggered the approval process, using the / endpoints.

Users can then call the endpoint to either approve / reject this activity. Of course this can also be done via the Dfns dashboard.

Chainalysis
Update Permission
Archive Permission
Assign Permission
Revoke Permission
Update Policy
Archive Policy
Generate Signature
Chainalysis
Chainalysis
"withdrawal attempt"
Chainalysis
register the transfer with Chainalysis
Get Approval
List Approvals
Create Approval Decision
Transfer Asset from Wallet
Broadcast Transaction from Wallet
Generate Signature from Wallet
Activity kind
Rule
Action
Filters
Approval
Wallets:Sign
Permissions:Assign
Permissions:Modify
Policies:Modify
AlwaysTrigger
TransactionAmountLimit
TransactionAmountVelocity
TransactionCountVelocity
TransactionRecipientWhitelist
Block
RequestApproval
alert is returned in Chainalysis results
here
here
direct exposure
here
address
Webhook Event
webhook event