# Transfer approval

Source: https://docs.settlemint.com/docs/compliance-security/compliance/transfer-approval
How the TransferApproval module gates regulated transfers with identity-bound approvals, expiry, consumption modes, and fee-feature exemptions.



TransferApproval requires an approval authority to grant permission before a regulated transfer executes. Each approval record names a sender identity, recipient identity, approved value, expiry window, and consumption mode. The compliance engine validates the record on every transfer attempt and consumes approval value only after the transfer succeeds. The indexed API gives you a review queue for the latest approval state, while the event log remains the lifecycle evidence source.

Related pages: [Compliance Overview](/docs/compliance-security/compliance), [Identity Verification](/docs/compliance-security/compliance/identity-verification), [Token holders and transfers](/docs/api-reference/tokens/token-holders-transfers#transfer-approval-workflows), [Supply & Investor Limits](/docs/compliance-security/compliance/supply-investor-limits), [Supply Cap & Collateral](/docs/compliance-security/compliance/supply-cap-collateral), [Asset Contracts](/docs/architects/components/asset-contracts).

## TransferApproval [#transferapproval]

TransferApproval requires pre-authorization before transfers. Each approval expires after a set duration. The approval mode controls consumption. The compliance engine can require an exact match, allow one transfer up to the cap, or permit multiple transfers until the approved total is spent.

### Interface (capabilities) [#interface-capabilities]

| Capability            | Who can call                 | Inputs                                                                    | On-chain effect                                                                       | Emits                      | Notes                                                                   |
| --------------------- | ---------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------- |
| `setModuleParameters` | Token admin (via compliance) | Approval authorities, expiry, and the installed module's parameter schema | Stores approval config; expiry is a config-time duration applied to all approvals     | None                       | Use approval-mode settings or exemption/one-time-use settings, not both |
| `approveTransfer`     | Approval authority           | Token, sender identity, recipient identity, value                         | Records approval for the sender, recipient, and approved amount with expiry timestamp | `TransferApproved`         | Only addresses in `approvalAuthorities` can issue approvals             |
| `revokeApproval`      | Approval authority           | Token, sender identity, recipient identity, value                         | Removes the active approval record                                                    | `TransferApprovalRevoked`  | Any configured approval authority can revoke a pending approval         |
| `canTransfer`         | Compliance engine            | Sender, recipient, amount                                                 | Checks the approval record and applies the configured approval mode                   | None                       | Validation only; consumption happens after a successful transfer        |
| `transferred`         | Compliance engine            | Token, sender, recipient, amount                                          | Marks consumed approval value after the transfer completes                            | `TransferApprovalConsumed` | Called by the engine after transfer execution                           |

### How pre-approval works [#how-pre-approval-works]

1. A compliance manager configures the approval authorities, the expiry duration, and the parameter model used by the installed module.
2. An approval authority issues an approval for a sender identity, recipient identity, and approved value.
3. The holder attempts a transfer between those identities.
4. The module checks that the approval is still active, not expired, and valid for the requested amount under the configured consumption rule.
5. After a successful transfer, the engine calls the transfer hook and the module records consumed approval value, emitting `TransferApprovalConsumed` where applicable.
6. If validation fails, the compliance engine blocks the transfer before consumption.

### Approval lifecycle [#approval-lifecycle]

<Mermaid
  chart="flowchart LR
  Authority[Approval authority] -->|approveTransfer| Pending[Pending approval]
  Pending -->|validated transfer succeeds| Consumed[Consumed approval]
  Pending -->|revokeApproval| Revoked[Revoked approval]
  Pending -->|expiry passes| Expired[Rejected during validation]
  Consumed --> Events[On-chain event log]
  Revoked --> Events
  Events --> Indexer[Indexed approvals API]"
/>

The event log records lifecycle decisions. The indexed approvals API holds the current approval state for the token and chain, so operators can review approvals by status (pending, consumed, or revoked) without replaying events on every check. Together, these records show whether an approval authority granted a transfer, whether the approval remained usable, and what happened when the holder attempted the transfer.

### API and integration surface [#api-and-integration-surface]

Use the token transfer approval API when your external workflow needs to inspect, create, or cancel TransferApproval records for a token. The list endpoint is the review surface for indexed approvals, not a replacement for the event log.

| Operation       | Endpoint                                                           | Use it for                                                                        |
| --------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| List approvals  | `GET /api/v2/tokens/{tokenAddress}/transfer-approvals`             | Reading indexed approvals, including `pending`, `consumed`, and `revoked` records |
| Create approval | `POST /api/v2/tokens/{tokenAddress}/transfer-approvals`            | Recording a sender-to-recipient approval before the holder initiates the transfer |
| Revoke approval | `POST /api/v2/tokens/{tokenAddress}/transfer-approval-revocations` | Cancelling a pending approval that should no longer execute                       |

The list endpoint reads indexed `TransferApprovalComplianceModule` events and returns paginated `data`, `meta`, and `links` fields. The indexed approval key includes the module address, token, sender identity, recipient identity, and approved value. API records expose that key as the composite `id`. Each row also carries the token, sender identity, recipient identity, and approver identity alongside the approved value and expiry, the current status, and creation and last-update timestamps.

By default, the collection sorts by newest approval first. Use `filter[status]` with `pending`, `consumed`, or `revoked` to narrow the list. Sort by `createdAt`, `updatedAt`, or `value` when an integration needs a stable review queue.

A `pending` record means the latest indexed lifecycle state for that approval tuple is a grant or re-grant. Earlier consume or revoke events can still exist for the same tuple. Check `expiry` before presenting the record as usable, and keep the transfer result with the review evidence when the holder used the approval.

An approval authority for the installed TransferApproval module must submit create and revoke operations. Both require `fromWallet`, `toWallet`, and a positive `amount` in base units. If the integration already knows both identity contract addresses from the approvals list, it may also send both `fromIdentityAddress` and `toIdentityAddress`. The platform rejects partial identity overrides. For request examples and operational retry guidance, see [Token holders and transfers](/docs/api-reference/tokens/token-holders-transfers#transfer-approval-workflows).

### Approval modes [#approval-modes]

Use the approval mode to control how narrowly the compliance engine consumes approvals you issue.

| Mode         | Value | Consumption behavior                                                                                                                                                | Typical use                                                                                 |
| ------------ | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Exact amount | `0`   | One transfer must match the approved value exactly. After that transfer succeeds, the compliance engine marks the approval consumed and the holder cannot reuse it. | Strict regulated transfers where the approval record must match one settlement instruction. |
| Up to once   | `1`   | One transfer can use any amount up to the approved value. Transferring less than the approved value still consumes the approval.                                    | Workflows where the final settled amount may be lower than the pre-approved cap.            |
| Up to total  | `2`   | Multiple transfers can spend against the approval until the approved total is spent. Further transfers require a new approval or a higher amount.                   | Programmatic or staged settlement where one approval covers several partial transfers.      |

Approval modes do not remove the expiry check during normal transfer validation. Once the configured approval window has passed, validation rejects the approval even if unused value remains. When the platform operates in accounting-only scope, it skips validation but still runs post-transfer accounting hooks.

### Rewriting-feature compatibility [#rewriting-feature-compatibility]

TransferApproval is the one compliance module that needs extra setup when you use it on an asset that also has a rewriting feature, such as the [Transaction Fee](/docs/architects/components/token-features/transaction-fee) feature. Every other compliance module is compatible with rewriting features without changes.

A rewriting feature splits one transfer into legs. A transfer of value `V` with a fee becomes a recipient leg for the net amount plus a fee leg to the fee collector. The compliance engine checks each leg independently. The fee collector is a destination the approval authority never pre-approved, so without further configuration the compliance engine rejects the fee leg and the whole transfer reverts.

The [External Transaction Fee](/docs/architects/components/token-features/external-transaction-fee) feature works differently and does not rewrite the asset transfer into legs. The feature adds a separate fee-token transfer from the payer to the fee recipient on top of the asset operation, so the asset transfer keeps its original recipient and amount. Because the feature creates no extra asset leg, TransferApproval sees only the original transfer, and the External Transaction Fee feature needs no exemption.

Plan for this interaction when you configure TransferApproval alongside a fee feature:

| Approval mode | Behavior with a rewriting feature                                                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Up to once    | Compatible. The recipient leg delivers the net amount, which is within the approved cap, so the recipient leg passes.                                |
| Up to total   | Compatible. The recipient leg spends the net amount against the approved total, leaving the remainder for later transfers.                           |
| Exact amount  | Incompatible by design. The net amount delivered after the fee never equals the approved value, so the recipient leg cannot match an exact approval. |

To clear the fee leg, an approval authority exempts the fee collector for the token. The exemption waives only the TransferApproval check for transfers to that collector. Identity registration and every other compliance module still apply to the fee leg, so the exemption never opens a compliance-free path.

The platform enforces an exemption only while the authority that set it remains an approval authority. Removing that authority stops the platform from enforcing the exemption, but does not clear the stored record. If the same authority is later added back, the platform enforces its earlier exemptions again. When you rotate authorities, explicitly clear any exemptions that should no longer apply rather than relying on authority removal to retire them.

For the order in which fee features and compliance run on a transfer, see [Token features overview](/docs/architects/components/token-features#how-features-work).

### Configuration [#configuration]

Choose the parameter schema that matches the installed module. Use approval-mode settings or exemption/one-time-use settings in your payload, but not both.

For the approval-mode model, configure:

| Option                | Description                                                                                               |
| --------------------- | --------------------------------------------------------------------------------------------------------- |
| `approvalAuthorities` | Addresses authorized to issue or revoke approvals                                                         |
| `approvalMode`        | Consumption rule for approvals: exact amount, up to once, or cumulative up to total                       |
| `approvalExpiry`      | Duration in seconds, from 1 to 31,536,000 seconds; set at configuration time and applies to all approvals |

For the exemption model, configure:

| Option                | Description                                                                                               |
| --------------------- | --------------------------------------------------------------------------------------------------------- |
| `approvalAuthorities` | Addresses authorized to issue or revoke approvals                                                         |
| `oneTimeUse`          | If true, a matching approval is consumed after one successful transfer                                    |
| `approvalExpiry`      | Duration in seconds, from 1 to 31,536,000 seconds; set at configuration time and applies to all approvals |
| `allowExemptions`     | If true, recipients matching the exemption expression bypass the approval requirement                     |
| `exemptionExpression` | RPN expression identifying exempt investors                                                               |

Validation ignores extra keys that do not belong to the installed module's schema, so keep configuration payloads schema-specific and do not mix exemption settings with approval modes.

After configuration, the approval mode is fixed for that module instance. Deploy a new TransferApproval module to change the mode.

### Operating patterns [#operating-patterns]

| Pattern                   | Approval mode | Why it fits                                                                |
| ------------------------- | ------------- | -------------------------------------------------------------------------- |
| Exact settlement ticket   | Exact amount  | The approval record must match one transfer instruction.                   |
| Capped single transfer    | Up to once    | The final transfer may settle below the approved cap, but only once.       |
| Staged partial settlement | Up to total   | Several partial transfers may spend down one approved total before expiry. |

### Key invariants [#key-invariants]

* Each approval covers one specific sender identity, recipient identity, and approved value, plus an expiry and an approval mode. The platform does not treat an approval as a blanket permission for any transfer.
* An investor with multiple wallets shares the same identity, so one approval covers all wallets tied to that identity.
* `approvalExpiry` is a config-time duration. All approvals share the same expiry window; the platform does not support per-approval expiry overrides.
* Exact amount mode is the strictest pattern. Use up-to modes only when your operating process allows partial consumption.
* `approvalMode` is fixed after configuration. Redeploy the module to change the mode.
* The compliance engine rejects expired approvals during normal transfer validation; the approval authority must reissue. Accounting-only scoped modules can still run post-transfer accounting hooks even when the engine skipped validation.

### Operational signals [#operational-signals]

* `TransferApproved`: emitted when an approval authority grants a transfer approval
* `TransferApprovalConsumed`: emitted when the compliance engine fully consumes an approval. Exact amount and up-to-once approvals emit after the successful transfer. Up-to-total approvals emit only when the remaining approved amount reaches zero, not on every partial transfer.
* `TransferApprovalRevoked`: emitted when an approval authority revokes an approval
* Monitor for `ComplianceCheckFailed` revert errors in failed transactions when transfers lack valid approvals

### Evidence and review records [#evidence-and-review-records]

Use the on-chain event log as the audit trail for approval lifecycle decisions. The indexed approvals API is your review surface for the latest approval records on the configured chain and token. The indexer stores each approval by module address, token, sender identity, recipient identity, and approved value. The API reports the current status as `pending`, `consumed`, or `revoked` so you can check the state at any point.

For an evidence pack, pair the approval list with the lifecycle transactions that matter to your workflow. Keep the approval grant record, the transfer consumption record, the revocation record, and failed-transfer records together so a reviewer can see both the requested approval and the final transfer outcome.

| Review question                                              | Primary record                                                                     | Check before relying on it                                                                                  |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Was a transfer approved for these identities and this value? | `TransferApproved` event and approvals API row                                     | Sender identity, recipient identity, token, module address, value, and expiry                               |
| Is the approval still open for use?                          | Approvals API row with `status: pending`                                           | Expiry, transfer history, and remaining value for up-to-total approvals                                     |
| Was the approval used?                                       | Successful transfer transaction and `TransferApprovalConsumed` event where emitted | Approval mode, consumed value, and final transfer status                                                    |
| Was the approval cancelled?                                  | `TransferApprovalRevoked` event and approvals API row with `status: revoked`       | Revoking authority and timestamp                                                                            |
| Why did a transfer fail?                                     | Failed transaction with `ComplianceCheckFailed`                                    | Whether the approval was missing, expired, revoked, already consumed, or too small for the requested amount |

### Failure modes & edge cases [#failure-modes--edge-cases]

* Any configured approval authority can revoke a pending approval. The compliance engine does not consume revoked approvals.
* The compliance engine rejects a reuse of an exact amount or up-to-once approval after a successful transfer, because the approval has already been consumed.
* The compliance engine rejects spending more than the remaining value of an up-to-total approval during normal validation. In accounting-only scope, the engine skips validation and the post-transfer hook clamps the remaining approval value to zero for accounting.

## See also [#see-also]

* [Compliance Overview](/docs/compliance-security/compliance): module architecture and regulatory templates
* [Identity Verification](/docs/compliance-security/compliance/identity-verification): identity controls that can combine with transfer pre-approval
* [TimeLock](/docs/compliance-security/compliance/timelock): time-based restrictions that complement pre-approval patterns
* [Token holders and transfers](/docs/api-reference/tokens/token-holders-transfers#transfer-approval-workflows): API examples for creating and revoking transfer approvals
