# Building User-Level Approvals

User-level approvals allow individual users to control their token transfers through incoming and outgoing approvals. These work similarly to [collection-level approvals](/token-standard/examples/building-collection-approvals.md) with key restrictions.

We refer you to the collection-level examples and just apply the same logic to the user-level types with these differences.

## Key Differences from Collection Approvals

* **Fixed Address Lists**:
  * Incoming approvals: `fromListId` is locked to the user's address
  * Outgoing approvals: `toListId` is locked to the user's address
* **No Override Functionality**: Cannot override other approval levels
* **User-Controlled**: Only the user can update their own approvals

## Incoming Approvals

Control what tokens the user can receive:

```typescript
const userIncomingApproval = {
    fromListId: 'user-address', // Locked to approver's address
    toListId: 'All', // Can specify recipients
    initiatedByListId: 'All',
    transferTimes: [{ start: '1', end: '18446744073709551615' }],
    tokenIds: [{ start: '1', end: '100' }],
    ownershipTimes: [{ start: '1', end: '18446744073709551615' }],
    approvalId: 'user-incoming-approval',

    // Use any approval criteria from collection examples
    approvalCriteria: {
        // See: transferable-approval.md, burnable-approval.md, etc.
        // OR use EmptyApprovalCriteria for no restrictions
        ...EmptyApprovalCriteria,
    },
};
```

## Outgoing Approvals

Control what tokens the user can send:

```typescript
const userOutgoingApproval = {
    fromListId: 'All', // Can specify senders
    toListId: 'user-address', // Locked to approver's address
    initiatedByListId: 'All',
    transferTimes: [{ start: '1', end: '18446744073709551615' }],
    tokenIds: [{ start: '1', end: '100' }],
    ownershipTimes: [{ start: '1', end: '18446744073709551615' }],
    approvalId: 'user-outgoing-approval',

    // Use any approval criteria from collection examples
    approvalCriteria: {
        // See: transferable-approval.md, burnable-approval.md, etc.
        // OR use EmptyApprovalCriteria for no restrictions
        ...EmptyApprovalCriteria,
    },
};
```

## Implementation

Users update their approvals via `MsgUpdateUserApprovals`:

```typescript
const updateUserApprovals = {
    creator: 'bb1...', // Your address
    collectionId: '1',
    updateIncomingApprovals: true,
    incomingApprovals: [userIncomingApproval],
    updateOutgoingApprovals: true,
    outgoingApprovals: [userOutgoingApproval],
    // ...
};
```

## Reference

For approval criteria examples, see:

* [Empty Approval Criteria](/token-standard/examples/empty-approval-criteria.md) - No restrictions template
* [Transferable Approval](/token-standard/examples/approvals/transferable-approval.md) - Basic transfer restrictions
* [Burnable Approval](/token-standard/examples/approvals/burnable-approval.md) - Burn functionality
* [Address Checks](/token-standard/learn/approval-criteria/address-checks.md) - Address type restrictions
* [EVM Query Challenges](/token-standard/learn/approval-criteria/evm-query-challenges.md) - Token-gating via EVM contract queries
* [Building Collection Approvals](/token-standard/examples/building-collection-approvals.md) - Collection-level patterns

For concepts, see:

* [Transferability](/token-standard/learn/transferability.md)
* [Approval Criteria](/token-standard/learn/approval-criteria.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bitbadges.io/token-standard/examples/building-user-approvals.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
