# Transfer approval

Source: https://docs.settlemint.com/docs/architecture/security/compliance/transfer-approval
Configure and review TransferApproval controls for identity-bound transfer pre-authorisation, expiry, consumption modes, and evidence collection.



TransferApproval adds identity-bound pre-authorisation to regulated transfers. Each approval is tied to a sender identity, recipient identity, approved value, expiry window, and configured consumption mode. Approval authorities can grant or revoke approvals. The compliance engine consumes them after a successful transfer, while the indexed API gives operators a review queue for the latest approval state.

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

## TransferApproval [#transferapproval]

TransferApproval requires pre-authorization before transfers. Approvals expire after a configured duration. The configured approval mode determines whether an approval must be consumed by an exact transfer amount, by one transfer up to the approved amount, or by multiple transfers up to the approved total.

### 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, expiry, 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 transfer is blocked 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 records the current approval state for the token and chain, so operators can review pending, consumed, and revoked approvals without replaying events during every check.

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

Use the token transfer approval API when an 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 returns collection-style `data`, `meta`, and `links` fields. Approval records include the token, sender identity, recipient identity, approver identity, approved value, expiry, status, and created and updated timestamps. By default, the collection sorts by newest approval first. Use `filter[status]` with `pending`, `consumed`, or `revoked` to narrow the list, and 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 approval was used.

Create and revoke operations must be submitted by an approval authority for the
installed TransferApproval module. Both operations 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`; partial identity overrides
are rejected. For request examples and operational retry guidance, see [Token
holders and transfers](/docs/developer-guides/api-integration/token-holders-transfers#transfer-approval-workflows).

### Approval modes [#approval-modes]

Use the approval mode to choose how narrowly each approval can be consumed.

| Mode         | Value | Consumption behavior                                                                                                                                | Typical use                                                                                 |
| ------------ | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| Exact amount | `0`   | One transfer must match the approved value exactly. After that transfer succeeds, the approval is consumed and cannot be reused.                    | 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 exhausted. Further transfers require a new approval or 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. If a module is configured for accounting-only scope, validation can be skipped while post-transfer accounting hooks still run.

### Configuration [#configuration]

Choose the parameter schema that matches the installed module.

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                                                               |

Extra keys that do not belong to the installed module's schema are ignored by validation, so keep configuration payloads schema-specific instead of mixing exemption settings with approval modes.

After configuration, approval-mode behavior is fixed for that module instance. To change from one approval mode to another, deploy a new TransferApproval module with the desired 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]

* Approval is scoped to the sender identity, recipient identity, approved value, expiry, and configured approval mode. It is not a blanket approval for any transfer.
* An investor with multiple wallets uses the same identity, so the approval can apply across wallets tied to that identity.
* `approvalExpiry` is a config-time duration. All approvals use the same expiry window, not per-approval overrides.
* Exact amount mode is the strictest approval-mode pattern; up-to modes are useful only when the operating process allows partial consumption.
* `approvalMode` is fixed after configuration. Redeploy the module to change approval-mode behavior.
* Expired approvals are rejected during normal transfer validation; the approval authority must reissue. Accounting-only scoped modules can still run post-transfer accounting hooks after validation was skipped.

### Operational signals [#operational-signals]

* `TransferApproved`: emitted when an approval authority grants a transfer approval
* `TransferApprovalConsumed`: emitted when an approval is fully consumed. Exact amount and up-to-once approvals emit after the successful transfer that uses them. 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

### Audit and review boundary [#audit-and-review-boundary]

Use the on-chain event log as the audit trail for approval lifecycle decisions. The indexed approvals API is a 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`.

For an evidence pack, pair the approval list with the lifecycle transactions that matter to the workflow. Keep the approval grant, transfer consumption, revocation, 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. Revoked approvals cannot be consumed.
* Reusing an exact amount or up-to-once approval after a successful transfer is rejected because the approval has already been used
* Spending more than the remaining value of an up-to-total approval is rejected during normal transfer validation. In accounting-only scope, validation is skipped and the post-transfer hook clamps remaining approval value to zero for accounting.

## See also [#see-also]

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