> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bebop.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Token Approvals

> Set up ERC-20 token approvals so Bebop's router and settlement contracts can execute your trades.

Before settlement, the applicable contract needs permission to move your sell tokens. Call `approve()` on the ERC-20 token contract for the required amount.

This applies to both the RFQ API (router and settlement contracts) and Aggregation API (balance manager).

## Which Contract to Approve

Every quote response includes an `approvalTarget` field - this is the address you approve. Always use this value rather than hardcoding.

<Warning>
  **Never hardcode the approval address.** Always read `approvalTarget` from the quote response.

  RFQ API quotes may return the router contract, settlement contract, or Permit2, depending on the flow.

  The Aggregation API uses a separate balance manager contract for approvals - it is not the same as the settlement contract.

  For Aggregation API, approving the settlement contract will lead to loss of funds.
</Warning>

## Check Existing Allowance

Before approving, check whether the token already has sufficient allowance. This avoids unnecessary gas spend on redundant approval transactions.

```python theme={null}
from web3 import Web3

ERC20_ABI = [
    {
        "constant": True,
        "inputs": [
            {"name": "_owner", "type": "address"},
            {"name": "_spender", "type": "address"},
        ],
        "name": "allowance",
        "outputs": [{"name": "", "type": "uint256"}],
        "type": "function",
    },
    {
        "constant": False,
        "inputs": [
            {"name": "_spender", "type": "address"},
            {"name": "_value", "type": "uint256"},
        ],
        "name": "approve",
        "outputs": [{"name": "", "type": "bool"}],
        "type": "function",
    },
]

w3 = Web3(Web3.HTTPProvider("https://eth.llamarpc.com"))

def check_allowance(owner: str, token_address: str, spender: str) -> int:
    token = w3.eth.contract(
        address=Web3.to_checksum_address(token_address),
        abi=ERC20_ABI,
    )
    return token.functions.allowance(
        Web3.to_checksum_address(owner),
        Web3.to_checksum_address(spender),
    ).call()
```

## Approve if Needed

If the current allowance is less than the trade amount, submit an approval transaction. Most integrators approve the maximum amount (`2^256 - 1`) so they only need to do this once per token.

```python theme={null}
from eth_account import Account

PRIVATE_KEY = "0x<your_private_key>"

def ensure_allowance(account, token_address: str, spender: str, required: int):
    current = check_allowance(account.address, token_address, spender)
    if current >= required:
        return  # already approved

    token = w3.eth.contract(
        address=Web3.to_checksum_address(token_address),
        abi=ERC20_ABI,
    )

    tx = token.functions.approve(
        Web3.to_checksum_address(spender),
        2**256 - 1,  # max approval
    ).build_transaction({
        "from": account.address,
        "nonce": w3.eth.get_transaction_count(account.address),
        "gasPrice": w3.eth.gas_price,
    })

    signed = w3.eth.account.sign_transaction(tx, private_key=PRIVATE_KEY)
    tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
    w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
```

## Using It with Quotes

After receiving a quote from either API, check and approve before signing and broadcasting:

```python theme={null}
quote = response.json()

sell_token = list(quote["sellTokens"].keys())[0]
sell_amount = int(quote["sellTokens"][sell_token]["amount"])
approval_target = quote["approvalTarget"]

account = Account.from_key(PRIVATE_KEY)
ensure_allowance(account, sell_token, approval_target, sell_amount)

# Now proceed to sign and broadcast...
```

## Approval Strategies

**Max approval (recommended for programmatic integrators):** Approve `2^256 - 1` once per token. Saves gas on subsequent trades since you never need to re-approve. This is the standard approach for solvers and aggregators.

**Exact approval:** Approve only the exact trade amount each time. More conservative, but costs gas on every trade. Some compliance-sensitive integrations prefer this.

## Approval type

The public RFQ and Aggregation APIs use `approval_type=Standard`.

For BebopRouter trades, see [Permit2 for self-execution](/rfq-api/guides/router-migration-guide#permit2-self-execution).

Always approve the `approvalTarget` from the current quote.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.