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

# Redemption

> Exchange PAXGy for PAXG using the REST calldata endpoints, and track or cancel an open request

Redemption is **not instant**. You submit a request offering PAXGy for PAXG, and once it is fulfilled the PAXG is delivered to your wallet. Plan your UX around a pending state.

<Info>
  The endpoints are named `withdraw` because they are shared across Paxos Labs
  yield products. For PAXGy, a withdrawal **is** a redemption.
</Info>

<Warning>
  Redemption happens on **Ethereum mainnet only** (`chainId: 1`). PAXG does not
  exist on X Layer, so there is nothing to redeem into there. PAXGy held on
  X Layer must be
  [transferred back to Ethereum](/v1.0.0/intro/products/paxgy/api-calldata/cross-chain)
  before it can be redeemed.
</Warning>

## Step 1: Quote the fee

Do this first. The fee is deducted from the PAXGy you offer, and you need it to size the approval in step 2.

```bash theme={null}
curl -G "https://api.paxoslabs.com/v2/amplify/calculateWithdrawalFee" \
  -H "x-api-key: pxl_your_key" \
  --data-urlencode "vaultAddress=0x6c6494Fd9962eB98B94ffA48F6679058F820700e" \
  --data-urlencode "wantAsset=0x45804880De22913dAFE09f4980848ECE6EcbAf78" \
  --data-urlencode "offerAmount=1000000000000000000" \
  --data-urlencode "chainId=1"
```

```json theme={null}
{
  "feeAmount": "0.0035",
  "offerFeePercentage": { "bps": 35, "percentage": "0.3500", "type": "dynamic" },
  "flatFee": "0"
}
```

`feeAmount` is authoritative for the amount you passed. The PAXGy redemption fee has two parts: a fixed rate charged on every redemption, plus a variable component that appears only when PAXG trades above its gold peg. That is why the rate is marked `dynamic` and why you should quote per request rather than caching a percentage.

## Step 2: Approve the redemption queue

<Warning>
  Approve the **redemption queue**, not the PAXGy token address, and approve
  `offerAmount + feeAmount`, not just `offerAmount`. The queue pulls the
  inclusive amount, so an exact-share approval reverts.
</Warning>

`feeAmount` comes back **formatted** (`"0.0035"`), not in base units, so convert it against the share token's decimals before adding it to `shareAmount`:

```typescript theme={null}
import { erc20Abi, parseUnits } from 'viem'

const PAXGY = '0x6c6494Fd9962eB98B94ffA48F6679058F820700e'
const REDEMPTION_QUEUE = '0x69e0BF658bE5600864A946b4e5B911736D248FB4'

const shareDecimals = await publicClient.readContract({
  address: PAXGY,
  abi: erc20Abi,
  functionName: 'decimals',
})

// shareAmount is already in base units; feeAmount is not.
const total = BigInt(shareAmount) + parseUnits(fee.feeAmount, shareDecimals)

await walletClient.writeContract({
  address: PAXGY,
  abi: erc20Abi,
  functionName: 'approve',
  args: [REDEMPTION_QUEUE, total],
})
```

Also bail out early when the fee is greater than or equal to `shareAmount`, because the post-fee math underflows on-chain and the request reverts. Compare in base units, using the converted value above.

## Step 3: Prepare the redemption

```bash theme={null}
curl -G "https://api.paxoslabs.com/v2/amplify/withdraw" \
  -H "x-api-key: pxl_your_key" \
  --data-urlencode "vaultAddress=0x6c6494Fd9962eB98B94ffA48F6679058F820700e" \
  --data-urlencode "wantAsset=0x45804880De22913dAFE09f4980848ECE6EcbAf78" \
  --data-urlencode "shareAmount=1000000000000000000" \
  --data-urlencode "userAddress=0xYourWallet" \
  --data-urlencode "chainId=1"
```

### Parameters

| Parameter        | Type     | Required | Description                                                                                                                      |
| ---------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `vaultAddress`   | `string` | Yes      | The PAXGy token address                                                                                                          |
| `wantAsset`      | `string` | Yes      | PAXG                                                                                                                             |
| `shareAmount`    | `string` | Yes      | PAXGy to redeem, in base units                                                                                                   |
| `userAddress`    | `string` | Yes      | Wallet sending the transaction                                                                                                   |
| `chainId`        | `number` | Yes      | EVM chain ID                                                                                                                     |
| `receiver`       | `string` | No       | Who receives the PAXG. Defaults to `userAddress`                                                                                 |
| `refundReceiver` | `string` | No       | Who receives the PAXGy back if the request cannot be filled. Defaults to `userAddress`                                           |
| `slippageBps`    | `number` | No       | Supported only for accounts enabled for direct settlement. PAXGy redemptions go through the queue, so passing it returns a `400` |

### Response

```json theme={null}
{
  "transaction": {
    "to": "0x69e0BF658bE5600864A946b4e5B911736D248FB4",
    "data": "0x...",
    "value": "0"
  },
  "estimatedWithdrawalLatency": "86400s"
}
```

Broadcast the `transaction` the same way as a mint.

## Settlement estimate

`estimatedWithdrawalLatency` is how long this redemption is expected to take, as a duration string. It is banded by how the order compares to liquidity that is not already claimed by earlier pending orders:

| Band      | When                                                                         | Value                |
| --------- | ---------------------------------------------------------------------------- | -------------------- |
| Immediate | The order fits the PAXG on hand, after pending orders ahead of it are served | `86400s` (24 hours)  |
| Standard  | Larger than that, but within 10% of vault TVL                                | `604800s` (7 days)   |
| Extended  | Above that share of TVL                                                      | `2592000s` (30 days) |

Two things to hold onto:

* **It is indicative, not a guarantee.** The bands are computed from liquidity at the moment you call the endpoint. A large order submitted ahead of yours between preparing and broadcasting can move you into a slower band than the one you were quoted.
* **The field may be absent.** It is omitted rather than guessed when the underlying data is briefly unavailable, and it is not returned for products that settle in the same transaction. Treat a missing value as "unknown" and fall back to your default messaging. Do not read it as "instant".

<Info>
  Splitting one large redemption into several smaller ones does not reliably
  land them all in the faster band: each order consumes available liquidity for
  the ones behind it, so later slices band slower as the queue fills.
</Info>

## Step 4: Track the request

```bash theme={null}
curl -G "https://api.paxoslabs.com/v2/amplify/withdrawalRequests" \
  -H "x-api-key: pxl_your_key" \
  --data-urlencode "filter=userAddress=0xYourWallet AND chainId=1"
```

Each request carries a `status`:

| Status           | Meaning                                        |
| ---------------- | ---------------------------------------------- |
| `PENDING`        | Open and cancellable                           |
| `COMPLETE`       | Filled, PAXG delivered                         |
| `PENDING_REFUND` | Cannot be filled; the PAXGy is on its way back |
| `REFUNDED`       | The PAXGy has been returned                    |

You can also filter on it directly:

```bash theme={null}
--data-urlencode "filter=userAddress=0xYourWallet AND chainId=1 AND status=PENDING"
```

<Warning>
  Handle the refund states. A request that cannot be fulfilled returns your
  PAXGy rather than delivering PAXG, and a UI that only models
  pending → complete will show the user a request that never resolves.
</Warning>

## Cancelling

While a request is still pending, prepare a cancellation with its order index:

```bash theme={null}
curl -G "https://api.paxoslabs.com/v2/amplify/withdraw/cancel" \
  -H "x-api-key: pxl_your_key" \
  --data-urlencode "vaultAddress=0x6c6494Fd9962eB98B94ffA48F6679058F820700e" \
  --data-urlencode "orderIndex=42" \
  --data-urlencode "chainId=1"
```

Only the wallet that created the request can cancel it. This is enforced on-chain, so the prepared calldata will revert if sent from anywhere else.

## Next

<CardGroup cols={2}>
  <Card title="Minting" icon="arrow-down" href="/v1.0.0/intro/products/paxgy/api-calldata/minting">
    Deposit PAXG and receive PAXGy.
  </Card>

  <Card title="Cross-chain" icon="arrows-left-right" href="/v1.0.0/intro/products/paxgy/api-calldata/cross-chain">
    Move PAXGy between Ethereum and X Layer.
  </Card>
</CardGroup>
