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

# Partial Fills

> Let an order settle for the size that's actually available - and get the rest back.

Sometimes the right outcome is most of the trade rather than none of it. With partial fills enabled, an order settles for whatever size is actually available at execution - the pattern of choice when firm liquidity is one ingredient in a larger route, or when a shrinking market makes a partial win better than a full miss.

<Note>
  Partial fills are opt-in per intent: set `intent.partialFill: true` on the quote request. Orders without the flag are all-or-nothing - they settle in full or refund in full.
</Note>

## The Mechanics

Partial-fill behavior is declared, not engineered: the flag rides on your intent, LPs quote knowing partial settlement is acceptable, and the escrow enforces proportionality - whatever fraction of your input is consumed, you receive at least the matching fraction of the quoted output. The unconsumed remainder of your input is released back to you.

There is no calldata surgery on your side. The signed order already encodes the partial-fill terms, and the settlement contract derives the fill arithmetic - your integration just reads the outcome.

## What a Partial Outcome Looks Like

A partially filled order reports both sides of the story:

```
requested input : 1000000000  (1,000 USDC)
consumed input  :  650000000  (650 USDC settled)
delivered output:  649350000  (per the quoted rate, proportionally enforced)
refunded input  :  350000000  (350 USDC released back)
```

| Aspect            | Guarantee                                                            |
| ----------------- | -------------------------------------------------------------------- |
| Rate              | The fill settles at no worse than the quoted rate, pro-rata          |
| Remainder         | Unconsumed input is released by the escrow, not left locked          |
| Atomicity per leg | Each settled portion is delivery-versus-payment, same as a full fill |

## In Practice

### 1. Quote with the Flag

```python theme={null} theme={null}
import httpx

API = "https://api.tetrafi.io/api/v1"
ME = "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693"
headers = {"X-API-Key": "tfk_live_..."}

resp = httpx.post(
    f"{API}/rfq/quotes",
    json={
        "user": ME,
        "intent": {
            "intentType": "swap",
            "inputs": [{"user": ME,
                        "asset": {"chainId": 10, "address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"},
                        "amount": "1000000000"}],   # 1,000 USDC
            "outputs": [{"receiver": ME,
                         "asset": {"chainId": 8453, "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}],
            "swapType": "ExactInput",
            "partialFill": True,
        },
        "supportedTypes": ["escrow-v0"],
    },
    headers=headers,
)
quotes = resp.json()["quotes"]
```

Key response behavior:

| Field              | With `partialFill: true`                                        |
| ------------------ | --------------------------------------------------------------- |
| `preview.outputs`  | The full-size delivery if the whole order fills                 |
| quote's fill terms | Carry the pro-rata floor the escrow will enforce on any portion |

### 2. Preflight, Sign, Submit

Nothing changes in your execution code - the partial-fill terms are already inside the payload you sign:

```python theme={null} theme={null}
from eth_account import Account
from eth_account.messages import encode_typed_data

selected = quotes[0]

pf = httpx.post(f"{API}/rfq/orders/preflight", headers=headers,
                json={"quoteResponse": selected}).json()

sign_action = next(a for a in pf["nextActions"] if a["purpose"] == "orderSignature")
signable = encode_typed_data(full_message=sign_action["typedData"])
signature = Account.sign_message(signable, private_key="0x<your_private_key>").signature.hex()

order = httpx.post(f"{API}/rfq/orders",
                   headers={**headers, "Idempotency-Key": selected["quoteId"]},
                   json={"quoteResponse": selected, "signature": signature}).json()
```

### 3. Read the Settled Amounts

Check the final order record for what actually filled versus what came back:

```python theme={null} theme={null}
import time

while True:
    o = httpx.get(f"{API}/rfq/orders/{order['id']}", headers=headers).json()
    if o["status"] in ("settled", "failed"):
        break
    time.sleep(2)

print("status:", o["status"])
# A settled partial fill reports the consumed input, delivered output,
# and refunded remainder on the order record.
```

## End to End

```python theme={null} theme={null}
import time

import httpx
from eth_account import Account
from eth_account.messages import encode_typed_data

API = "https://api.tetrafi.io/api/v1"
KEY = "tfk_live_..."
PRIVATE_KEY = "0x<your_private_key_hex>"
ME = "0x2e7E7cc62919eAf4c502dAC34753cFc5A29e9693"

headers = {"X-API-Key": KEY}

# --- 1. Quote 1,000 USDC with partial fills allowed ---
quotes = httpx.post(f"{API}/rfq/quotes", headers=headers, json={
    "user": ME,
    "intent": {
        "intentType": "swap",
        "inputs": [{"user": ME,
                    "asset": {"chainId": 10, "address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85"},
                    "amount": "1000000000"}],
        "outputs": [{"receiver": ME,
                     "asset": {"chainId": 8453, "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"}}],
        "swapType": "ExactInput",
        "partialFill": True,
    },
    "supportedTypes": ["escrow-v0"],
}).json()["quotes"]

selected = quotes[0]
print("Quoted by:", selected["solverId"])

# --- 2. Preflight and sign ---
pf = httpx.post(f"{API}/rfq/orders/preflight", headers=headers,
                json={"quoteResponse": selected}).json()
sign_action = next(a for a in pf["nextActions"] if a["purpose"] == "orderSignature")
signable = encode_typed_data(full_message=sign_action["typedData"])
signature = Account.sign_message(signable, private_key=PRIVATE_KEY).signature.hex()

# --- 3. Submit ---
order = httpx.post(f"{API}/rfq/orders",
                   headers={**headers, "Idempotency-Key": selected["quoteId"]},
                   json={"quoteResponse": selected, "signature": signature}).json()

# --- 4. See how much filled ---
while True:
    o = httpx.get(f"{API}/rfq/orders/{order['id']}", headers=headers).json()
    if o["status"] in ("settled", "failed"):
        print("final:", o["status"])
        break
    time.sleep(2)
```
