Skip to main content

Security Factors

Security Factors is a per-client address control system for outbound transfers. Each entry is either a WHITELIST (trusted) or BLACKLIST (blocked) factor, giving you fine-grained control over which destinations are allowed or denied.
  • WHITELIST entries mark addresses as pre-approved. They can be used as sweep rule targets and pass outbound transfer checks without triggering additional approval flows.
  • BLACKLIST entries explicitly block addresses. Transfers to blacklisted destinations are rejected outright, regardless of other approval rules.

Use Cases

  • Sweep target: In addition to your own VAULT accounts, sweep rules can forward funds to any whitelisted external address (e.g. an exchange hot wallet, a multisig, a custodian).
  • Outbound allow-list: Whitelisted destinations are considered pre-approved; transfers to non-whitelisted addresses may go through stricter approval flows.
  • Sanctions / fraud blocking: Blacklisted addresses are hard-blocked. Any transfer attempt targeting a blacklisted address is rejected immediately.

Scope

  • Client-scoped: A single security-factors list per client, shared across all wallets and accounts under that client.
  • Chain-bound: Each entry is tied to a specific chain. The same address string on ethereum and base is treated as two separate entries.

MFA Requirement

POST /security-factors (Add), PUT /security-factors/:factor_id/status (Update status), and DELETE /security-factors/:factor_id (Delete) require TOTP (2FA) verification. A user without 2FA configured cannot manage security factors — this is an intentional protection: an attacker with a stolen session cannot silently widen or wipe the allow-list, nor remove a block. The list endpoint (GET /security-factors) does not require MFA.

API Endpoints

All endpoints live under the authenticated /v1/client prefix.

List security factor entries

GET /v1/client/security-factors?chain=ethereum&factor_type=WHITELIST
Query parameters:
ParameterTypeDescription
chainstringOptional filter; returns all chains when omitted
factor_typestringOptional filter; WHITELIST or BLACKLIST. Returns both when omitted
statusstringOptional filter; active or inactive. Returns all when omitted
Response:
{
  "items": [
    {
      "factor_id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
      "factor_type": "WHITELIST",
      "chain": "ethereum",
      "address": "0xe37094f37695eAE7472394c73811F22E5DCf3C3d",
      "label": "Binance Hot Wallet",
      "status": "active",
      "reason": "",
      "added_by": "u_01HXYZ...",
      "created_at": "2026-04-15T10:00:00Z"
    }
  ],
  "total": 1
}

Add a security factor entry

POST /v1/client/security-factors
Content-Type: application/json

{
  "factor_type": "WHITELIST",
  "chain": "ethereum",
  "address": "0xe37094f37695eAE7472394c73811F22E5DCf3C3d",
  "label": "Binance Hot Wallet",
  "reason": "",
  "mfa_code": "123456"
}
Body fields:
FieldRequiredDescription
factor_typeyesWHITELIST (trusted) or BLACKLIST (blocked)
chainyesTarget chain (ethereum, bsc, polygon, base, tron, solana, etc.)
addressyesDestination address (raw format per chain — EVM mixed-case preserved, Base58 as-is)
labelnoUser-assigned name (max 100 chars), e.g. "My Exchange Cold Wallet"
reasonnoFree-text reason for adding this entry (max 255 chars), e.g. "OFAC sanctioned address"
mfa_codeyes6-digit TOTP code from your authenticator app
Response: the created entry (same shape as list item).

Update security factor status

PUT /v1/client/security-factors/a1b2c3d4-e5f6-7890-1234-567890abcdef/status
Content-Type: application/json

{
  "status": "inactive",
  "mfa_code": "123456"
}
Body fields:
FieldRequiredDescription
statusyesactive or inactive
mfa_codeyes6-digit TOTP code from your authenticator app
Response: the updated entry (same shape as list item).

Delete a security factor entry

DELETE /v1/client/security-factors/a1b2c3d4-e5f6-7890-1234-567890abcdef
Content-Type: application/json

{ "mfa_code": "123456" }
Response: HTTP 200 on success.

Uniqueness

The combination (client_id, factor_type, chain, address) must be unique per active entry. Attempting to add a duplicate returns SECURITY_FACTOR_ALREADY_EXISTS (409). Soft-deleted entries do not block re-adding the same address.

Errors

CodeHTTPMeaning
SECURITY_FACTOR_ALREADY_EXISTS409Address already exists with the same factor type on this chain
SECURITY_FACTOR_NOT_FOUND404factor_id does not exist for this client
MFA_REQUIRED400mfa_code missing but user has TOTP enabled
MFA_NOT_ENABLED400User has not configured 2FA; set it up first
MFA_INVALID400mfa_code is incorrect or has expired

Best Practices

  • Rotate labels — keep labels meaningful so operators can identify destinations at a glance.
  • Audit regularly — review the security factors list periodically and remove stale entries.
  • Protect 2FA — since add/update/delete require TOTP, protect the authenticator device as carefully as the API credentials themselves.
  • Use BLACKLIST for sanctions — proactively block known sanctioned or compromised addresses to prevent accidental transfers.