---
title: "Bulk update wallet policy rules"
method: PUT
path: "/api/v2/policy/rule/bulk"
tags: ["Wallet Policy"]
---

# Bulk update wallet policy rules

`PUT /api/v2/policy/rule/bulk`

Updates whitelist policy rules across multiple wallets in a single request.
Only advancedWhitelist rules are supported.

## Request body

- object
  - `updates` object[], required
    - `walletId` string, required — The ID of the wallet to update
    - `coin` string, required — The coin type for this rule
    - `id` string, required — The id of the rule
    - `type` 'advancedWhitelist', required — Must be advancedWhitelist
    - `action` BulkPolicyRuleAction, required — Action for a policy rule - simplified version of PolicyRuleAction that's Json-compatible (Original uses h.optionalized which creates intersection types incompatible with Json)
      - `type` string, required
      - `userIds` string[]
    - `condition` BulkWhitelistCondition, required — Condition for whitelist update - simplified version of AdvancedListRuleUpdateCondition
      - `add` BulkWhitelistAddEntry — Entry to add to the whitelist
        - `item` string, required
        - `type` string, required
        - `metaData` object
      - `remove` BulkWhitelistRemoveEntry — Entry to remove from the whitelist
        - `item` string, required
        - `type` string
      - `verifyItems` object
        - `items` string[], required
    - `lockDate` string — ISO date string for when the whitelist policy locks. Omit to auto-lock after ~48h.
    - `generatePolicy` boolean — When true, creates the wallet whitelist policy in the Policy Service if it doesn't exist
  - `batch` object — Set when this request is one of several splitting a single large submission
    - `groupId` string, required — Client-generated id shared by every request of one split submission. Bounded (non-empty, at most {@link MAX_BATCH_GROUP_ID_LENGTH} characters, alphanumeric plus `_`/`-`) because this value is persisted verbatim on the PendingApproval document and on the audit log entry (`ctx.getAudit().setData('batchGroupId', ...)`) — an unbounded or arbitrary-content string would let a caller store a large or control-character-laden value in both places. The restricted charset still admits a UUID v4, which is what clients are expected to send.
    - `index` number, required — Whole-number position or count within a batch. Declared here rather than reusing `t.Int` because the OpenAPI generator cannot derive encode/decode types for codecs branded inside io-ts's own declaration file, which fails the generated-spec CI check. Only integrality is enforced at the codec boundary; the `1 <= index <= total` relation stays in the controller so the failure is a descriptive 400 rather than a generic decode error.
    - `total` number, required — Whole-number position or count within a batch. Declared here rather than reusing `t.Int` because the OpenAPI generator cannot derive encode/decode types for codecs branded inside io-ts's own declaration file, which fails the generated-spec CI check. Only integrality is enforced at the codec boundary; the `1 <= index <= total` relation stays in the controller so the failure is a descriptive 400 rather than a generic decode error.

## Response `200`

OK

- BulkPolicyRuleUpdateResponse — Response for bulk policy rule update
  - `successes` unknown[]
    - unknown
  - `failures` object[]
    - `walletId` string, required
    - `error` string, required
  - `pendingAdminApproval` PendingApproval
    - `id` string, required
    - `coin` string — A cryptocurrency or token ticker symbol.
    - `wallet` string
    - `walletType` string
    - `walletSubType` string — The subtype of the wallet (e.g., custodialHot)
    - `wallets` string[]
    - `enterprise` string
    - `organization` string
    - `safeId` string — The safe the pending approval is scoped to
    - `organizationName` string — The organization name
    - `bitgoOrg` string — The BitGo organization
    - `creator` string, required
    - `createDate` string, date-time, required — The creation date of the pending approval
    - `approvedDate` string, date-time — The date when the approval was granted
    - `updatedAt` string, date-time — The date when the approval was last updated (any update, not just processing)
    - `keyCurve` 'secp256k1' | 'ed25519' | 'bls12_381' — The key curve of the coin attached to this pending approval
    - `info` PendingApprovalInfo, required
      - `type` 'userChangeRequest' | 'transactionRequest' | 'transactionRequestFull' | 'policyRuleRequest' | 'updateApprovalsRequiredRequest' | 'updateEnterpriseRequest' | 'updateOrganizationRequest' | 'genericRequest' | 'enterpriseInviteRequest' | 'updateWalletSettingRequest' | 'updateWalletTagsRequest', required
      - `userChangeRequest` object
        - `action` string — The action taken
        - `permissions` string[]
        - `userChanged` string — The user that changed
      - `transactionRequest` object
        - `buildParams` unknown
        - `coinSpecific` unknown
        - `comment` string, nullable — The comment for the transaction request
        - `fee` unknown
        - `isUnsigned` boolean, nullable — Indicates if the transaction is unsigned
        - `policyUniqueId` unknown
        - `recipients` object[]
          - `address` string — The address of the recipient
          - `amount` string — The amount to be transferred
          - `data` string — Additional data for the transaction
        - `requestedAmount` unknown
        - `sourceWallet` unknown
        - `triggeredPolicy` unknown
        - `validTransaction` string — Indicates if the transaction is valid
        - `validTransactionHash` string — The hash of the valid transaction
        - `verificationItems` string[], nullable — The verification items for the transaction
        - `verificationRuleId` string, nullable — The ID of the verification rule
        - `videoApprovers` unknown[]
          - unknown
      - `transactionRequestFull` object
        - `intent` union
          - object — ============================================================================ REUSABLE SCHEMA FRAGMENTS FOR ASSET-CONTAINING INTENTS ============================================================================ These schemas define reusable building blocks that concrete intent schemas can compose with. They serve multiple purposes: 1. **Schema Reuse**: Concrete intents can intersect with these fragments 2. **Pattern Matching**: getAssetsFromIntent utility matches against these 3. **Type Safety**: Ensures consistency across all asset-containing intents 4. **Documentation**: Clearly shows which intents handle which asset types By using the actual RecipientEntry and TokenRecipientEntry types, we ensure these patterns exactly match the structures used in concrete intents.
            - `intentType` 'payment', required — Must be "payment".
            - `sequenceId` string
            - `comment` string
            - `nonce` union — Override the on-chain nonce for this transaction.
              - …
            - `recipients` object[], required
              - …
          - object — ============================================================================ REUSABLE SCHEMA FRAGMENTS FOR ASSET-CONTAINING INTENTS ============================================================================ These schemas define reusable building blocks that concrete intent schemas can compose with. They serve multiple purposes: 1. **Schema Reuse**: Concrete intents can intersect with these fragments 2. **Pattern Matching**: getAssetsFromIntent utility matches against these 3. **Type Safety**: Ensures consistency across all asset-containing intents 4. **Documentation**: Clearly shows which intents handle which asset types By using the actual RecipientEntry and TokenRecipientEntry types, we ensure these patterns exactly match the structures used in concrete intents.
            - `intentType` 'payment', required — Must be "payment".
            - `sequenceId` string
            - `comment` string
            - `nonce` union — Override the on-chain nonce for this transaction.
              - …
            - `recipients` object[], required
              - …
            - `isTestTransaction` boolean, required — When true, marks this as a test transaction (not broadcast to the network).
        - `policyUniqueId` string — The unique ID for the policy
        - `txRequest` union — The transaction request details
          - TransactionRequestLite
            - `intent` union
              - …
            - `unsignedTxs` object[]
              - …
            - `signatureShares` object[]
              - …
            - `commitmentShares` object[]
              - …
            - `txHashes` string[]
            - `apiVersion` 'lite' | 'full' — The API version of the transaction request
            - `txRequestId` string, uuid, required
            - `idempotencyKey` string — The idempotency key of the transaction request
            - `walletId` string, required
            - `walletType` 'backing' | 'cold' | 'custodial' | 'custodialPaired' | 'hot' | 'advanced' | 'trading' — The type describes who owns the keys to the wallet associated to the TxRequest.
            - `version` number, required — The version of the transaction request
            - `enterpriseId` string — If the wallet that owns the TxRequest is owned by an enterprise then this is the Id of said enterprise.
            - `organizationId` string — The id of the organization the TxRequest's wallet belongs to.
            - `state` 'pendingApproval' | 'canceled' | 'rejected' | 'initialized' | 'pendingDelivery' | 'delivered' | 'pendingUserSignature' | 'pendingUserCommitment' | 'pendingUserRShare' | 'pendingUserGShare' | 'readyToSend' | 'signed' | 'failed', required
            - `date` string, date-time, required — The date and time this version of the TxRequest document was created.
            - `createdDate` string, date-time, required — The date and time the version 1 TxRequest document was created.
            - `userId` string, required — The Id of the User that produced this version of the TxRequest document. Could have created a new document or updated an existing document.
            - `initiatedBy` string, required — The Id of the User that originally created the TxRequest document (initiated the TxRequest).
            - `updatedBy` string, required — The Id of the User that last updated the TxRequest document. This is an alias for the userId field.
            - `intents` unknown[], required
              - …
            - `pendingApprovalId` string — The id of the Pending Approval that was created for the TxRequest if one was required.
            - `policiesChecked` boolean
            - `latest` boolean, required — Indicates if this is the latest transaction request
            - `isCanceled` boolean — True, if the transaction request is canceled.
            - `cancelReason` string — The reason the transaction request was canceled, if applicable.
            - `initiatedByDAppClient` boolean — True when the txRequest was initiated by a dApp OAuth client (e.g. Narval).
            - `txChannel` object — Immutable DeFi / marketplace channel classification (DEFI-300).
              - …
          - TransactionRequestFull
            - `transactions` object[]
              - …
            - `messages` object[]
              - …
            - `apiVersion` 'lite' | 'full' — The API version of the transaction request
            - `txRequestId` string, uuid, required
            - `idempotencyKey` string — The idempotency key of the transaction request
            - `walletId` string, required
            - `walletType` 'backing' | 'cold' | 'custodial' | 'custodialPaired' | 'hot' | 'advanced' | 'trading' — The type describes who owns the keys to the wallet associated to the TxRequest.
            - `version` number, required — The version of the transaction request
            - `enterpriseId` string — If the wallet that owns the TxRequest is owned by an enterprise then this is the Id of said enterprise.
            - `organizationId` string — The id of the organization the TxRequest's wallet belongs to.
            - `state` 'pendingApproval' | 'canceled' | 'rejected' | 'initialized' | 'pendingDelivery' | 'delivered' | 'pendingUserSignature' | 'pendingUserCommitment' | 'pendingUserRShare' | 'pendingUserGShare' | 'readyToSend' | 'signed' | 'failed', required
            - `date` string, date-time, required — The date and time this version of the TxRequest document was created.
            - `createdDate` string, date-time, required — The date and time the version 1 TxRequest document was created.
            - `userId` string, required — The Id of the User that produced this version of the TxRequest document. Could have created a new document or updated an existing document.
            - `initiatedBy` string, required — The Id of the User that originally created the TxRequest document (initiated the TxRequest).
            - `updatedBy` string, required — The Id of the User that last updated the TxRequest document. This is an alias for the userId field.
            - `intent` unknown
            - `intents` unknown[], required
              - …
            - `pendingApprovalId` string — The id of the Pending Approval that was created for the TxRequest if one was required.
            - `policiesChecked` boolean
            - `latest` boolean, required — Indicates if this is the latest transaction request
            - `isCanceled` boolean — True, if the transaction request is canceled.
            - `cancelReason` string — The reason the transaction request was canceled, if applicable.
            - `initiatedByDAppClient` boolean — True when the txRequest was initiated by a dApp OAuth client (e.g. Narval).
            - `txChannel` object — Immutable DeFi / marketplace channel classification (DEFI-300).
              - …
        - `txRequestId` string, uuid, required
        - `verificationItems` string[]
        - `verificationRuleId` string — The ID of the verification rule
        - `videoApprovers` string[]
        - `walletRebalanceEventId` string — The ID of the wallet rebalance event
      - `policyRuleRequest` object
        - `action` string — The action of the policy rule request
        - `batch` object — Present when this approval is one batch of a split submission
          - `groupId` string, required
          - `index` number, required
          - `total` number, required
        - `update` object — The update details of the policy rule request (single-wallet)
          - `action` PolicyRuleAction
            - `type` 'deny' | 'getApproval' | 'getEnterpriseUserApproval' | 'getUserRoleApproval' | 'getAnyApproval' | 'getFinalApproval' | 'getVideoApproval' | 'getIdVerification' | 'verifyWalletRebalance' | 'getCustodianApproval' | 'getCustodialSignature' | 'triggerWebhookNotification' | 'performLivenessVerification' | 'recommendBackingWalletRouting' | 'getManualTrustReview' | 'getManualSupportReview' | 'getSupportManagerApproval' | 'getVideoApprovalFromSupport' | 'evaluateFraudRisk', required
            - `userIds` string[]
          - `coin` string — A cryptocurrency symbol or token ticker symbol
          - `condition` union
            - AddressListRuleUpdateCondition
              - …
            - AdvancedListRuleUpdateCondition
              - …
            - TxUsdThresholdRuleCondition
              - …
            - LimitRuleCondition
              - …
            - WebhookRuleCondition
              - …
          - `generatePolicy` boolean — Should generate new whitelist policy when generatePolicy is undefined *
          - `id` string — The ID of the policy rule
          - `lockDate` string, date
          - `type` 'advancedWhitelist' | 'coinAddressWhitelist' | 'coinAddressBlacklist'
          - `walletId` string — Optional walletId field for multi-wallet updates
        - `updates` object[]
          - `action` PolicyRuleAction
            - `type` 'deny' | 'getApproval' | 'getEnterpriseUserApproval' | 'getUserRoleApproval' | 'getAnyApproval' | 'getFinalApproval' | 'getVideoApproval' | 'getIdVerification' | 'verifyWalletRebalance' | 'getCustodianApproval' | 'getCustodialSignature' | 'triggerWebhookNotification' | 'performLivenessVerification' | 'recommendBackingWalletRouting' | 'getManualTrustReview' | 'getManualSupportReview' | 'getSupportManagerApproval' | 'getVideoApprovalFromSupport' | 'evaluateFraudRisk', required
            - `userIds` string[]
          - `coin` string — A cryptocurrency symbol or token ticker symbol
          - `condition` union
            - AddressListRuleUpdateCondition
              - …
            - AdvancedListRuleUpdateCondition
              - …
            - TxUsdThresholdRuleCondition
              - …
            - LimitRuleCondition
              - …
            - WebhookRuleCondition
              - …
          - `generatePolicy` boolean — Should generate new whitelist policy when generatePolicy is undefined *
          - `id` string — The ID of the policy rule
          - `lockDate` string, date
          - `type` 'advancedWhitelist' | 'coinAddressWhitelist' | 'coinAddressBlacklist'
          - `walletId` string — Optional walletId field for multi-wallet updates
      - `updateApprovalsRequiredRequest` object
        - `requestedApprovalsRequired` number — The number of requested approvals required
      - `updateEnterpriseRequest` object
        - `action` 'add' | 'update' | 'remove'
        - `email` string — The email of the user
        - `isVideoIdUser` boolean — Indicates if the user is a video ID user
        - `permissions` 'admin' | 'auditor' | 'wallet.create' — The permissions associated with the update
        - `userId` string — The ID of the user
      - `updateOrganizationRequest` object
        - `action` 'add' | 'update' | 'remove'
        - `email` string — The email of the user
        - `inviterInfo` object — CaaS org add-invite only (`POST /api/v2/organization/{orgId}/user`); UMS org user changes use `genericRequest`.
          - `email` string, required
          - `fullName` string, required
          - `id` string, required
        - `role` 'serviceUser' | 'admin' | 'member' | 'customer' — The role of the user in the organization
        - `userId` string — The ID of the user
      - `genericRequest` object
        - `anchors` object[]
          - `anchorType` 'policyRuleId' | 'settlementId' | 'crossChainRecoveryId', required
          - `key` string, required — The key of the anchor
          - `value` string, required — The value of the anchor
        - `changeType` 'create' | 'update' | 'delete' | 'unlock' | 'bulkUnlock' | 'bulkArchive' | 'duplicate'
        - `currentId` string — The current ID associated with the request
        - `description` string — The description of the request
        - `metadata` object — The metadata of the request
        - `proposedId` string — The proposed ID associated with the request
        - `resources` object[]
          - `currentId` string
          - `metadata` object
          - `proposedId` string
        - `resourceType` string — The resource type of the request
      - `enterpriseInviteRequest` object
        - `action` 'add' | 'update' | 'remove'
        - `email` string — The email of the user
        - `enterpriseInfo` object — Additional info used by the client accepting the invite
          - `id` string, required
          - `invitedBy` CaasOrganizationInviteInviterInfo, required — Inviter snapshot on CaaS org add-invite `inviterInfo` and enterprise invite `invitedBy`. Not used for UMS `genericRequest`.
            - `id` string, required
            - `email` string, required
            - `fullName` string, required
          - `name` string, required
          - `requiredVerificationStep` string, required
          - `userKycState` string
        - `isVideoIdUser` boolean — Indicates if the user is a video ID user
        - `permissions` 'admin' | 'auditor' | 'wallet.create' — The permissions associated with the invite
        - `userId` string — The ID of the user
      - `updateWalletSettingRequest` object
        - `userKeySigningRequired` object
          - `newValue` boolean, required
          - `oldValue` boolean, required
      - `updateWalletTagsRequest` object
        - `action` 'add' | 'remove', required
        - `customTags` string[], required
    - `state` union, required
      - 'pending' | 'awaitingSignature' | 'pendingFinalApproval' | 'pendingCustodianApproval' | 'pendingVideoApproval' | 'pendingIdVerification' | 'pendingLivenessVerification' | 'pendingManualTrustReview' | 'pendingManualSupportReview' | 'pendingVideoApprovalFromSupport' | 'pendingFraudRiskEvaluation'
      - 'approved' | 'processing' | 'rejected'
      - 'pendingVideoApproval' | 'pendingIdVerification' | 'awaitingSignature' | 'pendingCustodianApproval' | 'pendingManualTrustReview' | 'pendingFraudRiskEvaluation'
      - 'pendingVideoApproval' | 'pendingIdVerification' | 'awaitingSignature' | 'pendingCustodianApproval' | 'pendingManualTrustReview' | 'pendingFraudRiskEvaluation'
    - `scope` 'enterprise' | 'wallet' | 'organization' | 'global' | 'safe', required — What kind of entity the Pending Approval is tied to
    - `userIds` string[]
    - `approvalsRequired` number
    - `walletLabel` string — Label for the wallet
    - `addressLabels` object[]
      - `address` string, required
      - `label` string, required — The label
      - `walletLabel` string — The wallet label
    - `resolvers` object[]
      - `autoApproved` boolean — Whether the resolution was auto approved
      - `date` string, date-time — The date of resolution
      - `resolutionAction` 'approve' | 'reject' | 'skip' | 'fail' — Action taken during resolution
      - `resolutionMemo` string — Memo regarding the resolution
      - `resolutionType` 'pending' | 'awaitingSignature' | 'pendingFinalApproval' | 'pendingCustodianApproval' | 'pendingVideoApproval' | 'pendingIdVerification' | 'pendingLivenessVerification' | 'pendingManualTrustReview' | 'pendingManualSupportReview' | 'pendingVideoApprovalFromSupport' | 'pendingFraudRiskEvaluation', required
      - `user` string — The user who resolved the approval
      - `videoApprover` string — The approver of the video resolution
      - `videoException` string — Exception details for the video
      - `videoLink` string — Link to the resolution video
    - `approvers` string[]
    - `singleRunResults` object[]
      - `ruleId` string — The rule ID
      - `triggered` boolean — Whether the rule was triggered
    - `txRequestId` string, uuid — Transaction request ID
    - `videoId` object — ID for the video related to the approval
      - `date` string, date-time — The date of the video ID
      - `user` string — The user associated with the video ID
      - `videoApprover` string — The approver of the video
      - `videoException` string — The exception related to the video
      - `videoLink` string — The link to the video
    - `version` number — Version of the pending approval
    - `policyEvaluationId` string — ID for the policy evaluation
    - `actions` object[]
      - `approvers` string[]
      - `excludedApprovers` string[]
      - `id` string, required — The ID of the action
      - `name` string, required — The name of the action
      - `operator` 'AND' | 'OR' — The operator of the action
      - `parameters` PolicyActionParameters, required
        - `minRequired` union
          - string
          - number
        - `userIds` string[]
        - `initiatorIsAllowedToApprove` boolean
        - `webhookURL` string
        - `livenessCheckUser` 'transactionInitiator' | 'walletAdmins' | 'videoIdUsers' | 'enterpriseAdmin'
        - `isFallback` boolean
        - `walletSubtype` 'custodialCold' | 'custodialHot' | 'lightningCustody'
        - `userRoleIds` string[]
      - `resolvers` object[]
        - `autoApproved` boolean — Whether the resolution was auto approved
        - `date` string, date-time — The date of resolution
        - `resolutionAction` 'approve' | 'reject' | 'skip' | 'fail' — Action taken during resolution
        - `resolutionMemo` string — Memo regarding the resolution
        - `resolutionType` 'pending' | 'awaitingSignature' | 'pendingFinalApproval' | 'pendingCustodianApproval' | 'pendingVideoApproval' | 'pendingIdVerification' | 'pendingLivenessVerification' | 'pendingManualTrustReview' | 'pendingManualSupportReview' | 'pendingVideoApprovalFromSupport' | 'pendingFraudRiskEvaluation', required
        - `user` string — The user who resolved the approval
        - `videoApprover` string — The approver of the video resolution
        - `videoException` string — Exception details for the video
        - `videoLink` string — Link to the resolution video
      - `status` 'SKIPPED' | 'PENDING' | 'NOT_NEEDED' | 'COMPLETE' | 'CANCELLED' | 'FAILED' | 'AUTO_CANCELLED', required
    - `resolutionOrder` object[]
      - `actions` string[], required
    - `useLegacyPolicyEngine` boolean — Flag to use legacy policy engine
    - `videoCallId` string — ID for the video call
    - `lastUpdated` string, date-time — The last date the approval was processing
    - `freeze` object — The freeze state
      - `actions` object[]
        - `reason` string
        - `state` 'frozen' | 'unFrozen'
        - `time` string, date-time
        - `userId` string
        - `username` string
      - `state` 'frozen' | 'unFrozen'
    - `memo` object[]
      - `text` string, required — The text of the memo
      - `time` string, date-time, required — The time the memo was created
      - `userId` string, required — The user ID of the admin who created the memo
      - `username` string, required — The username of the admin who created the memo
    - `associatedInquiries` object[]
      - `inquiryId` string, required
      - `inquiryStatus` 'completed' | 'failed', required
      - `inquirySubType` 'withdrawalLivenessCheck' | 'managePolicyLivenessCheck' | 'govIdSelfie', required
      - `inquiryType` 'livenessCheck', required
    - `securityControlEvents` object[]
      - `control` string — The security control that was evaluated
      - `date` string, date-time, required — The date the event was recorded
      - `ip` string — The IP address of the user
      - `message` string — Message from the security control
      - `result` 'allowed' | 'blocked', required — Whether the user was allowed or blocked
      - `user` string, required — The user who triggered the security control check
  - `travelRulePendingApprovals` unknown[]
    - unknown

## Other responses

- `400` — Bad Request
- `403` — Forbidden

---

[API](https://skmtc.net/bitgo/apis/bitgo-api.md) · [All operations](https://skmtc.net/bitgo/apis/bitgo-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/bitgo/bitgo-api/revisions/e445c15e5bee/schema)
