> For the complete documentation index, see [llms.txt](https://docs.dimes.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dimes.fi/for-developers/order-types/partial-open.md).

# Partial-Open (FAK) (coming soon)

By default, a quote opens **atomically**: the order either fills its full requested notional in a single fill-or-kill (FOK) match, or it reverts and the user is fully refunded — no position is created. Thin markets often can't absorb the full size in one match, so atomic opens on them fail more often than they need to.

**Partial-open** lets the user accept a smaller fill. Set `allow_partial_fill: true` on the quote and the position opens at the size that actually filled, down to an optional `min_fill_bps` floor.

## Enablement

Partial-open is **on by default** — there is no feature flag to turn on. It is gated only by a server-side kill switch. If that switch is active, a partial-open request is rejected with `quote_fak_order_type_disabled` (HTTP 403); fall back to an atomic order (omit `allow_partial_fill`).

## Request fields

Both fields live on the quote/offer/draft-quote request body:

| Field                | Type    | Required | Notes                                                                                 |
| -------------------- | ------- | -------- | ------------------------------------------------------------------------------------- |
| `allow_partial_fill` | boolean | no       | `false` (default) = atomic. `true` opts into partial-open.                            |
| `min_fill_bps`       | integer | no       | Minimum acceptable fill, in basis points. Only valid with `allow_partial_fill: true`. |

`min_fill_bps` rules (all enforced at quote creation, before any order is placed):

* Range **2000–5000** (20%–50%).
* Multiple of **500** (5% steps).
* At least the **floor cap** (see below).

Omit both fields for normal atomic behaviour — nothing changes.

## The `min_fill_bps` floor cap

A partial fill must never open a position below the protocol minimums. Because `min_fill_bps` is the *worst-case* fraction that can fill, the backend rejects any value that could breach a minimum. The floor is computed purely from the request — no market data, no fill required:

```
floor_min_fill_bps = max(
  2000,
  ceil(MIN_COLLATERAL × 10000 / requested_collateral),   // collateral bound
  ceil(MIN_NOTIONAL   × 10000 / requested_notional)       // notional bound
)
```

If `min_fill_bps < floor_min_fill_bps`, the request is rejected with `quote_min_fill_bps_below_floor` (see [Errors](#errors)). The collateral bound dominates at high leverage; the **notional bound dominates at low leverage** (below \~4x), where a small fraction of a small notional would otherwise fall under the minimum order size. When the floor exceeds the 5000 (50%) maximum, no partial fill is viable and the order must be atomic.

## Lifecycle

1. **Floor leg.** The backend posts an FOK sized at the requested floor (`floor_token_units = floor(target_token_units × min_fill_bps / 10000)`). If it never fills within the retry budget, the position is fully reverted — all collateral, origination fee, and prepaid venue fee are refunded — and the customer gateway emits `PARTIAL_OPEN_FLOOR_MISSED`.
2. **Chase the remainder.** Once the floor fills, the backend posts up to 3 fill-and-kill (FAK) retries (5s apart) for the unfilled remainder. Each fulfilled retry emits `PARTIAL_OPEN_PROGRESS` with the cumulative fill amount.
3. **Finalize.** When the retry budget is exhausted (or cumulative fill reaches the full target), `finalizeOpenPartial` shrinks the on-chain position to the actually-filled size while preserving the originally signed leverage. Unused collateral, borrowed amount, and venue fee are refunded proportionally.

## WebSocket notifications

Subscribe to the customer gateway `notification` event (see [WebSocket Events](/for-developers/api-and-events/websocket.md#notification-events-customer-gateway-only)):

| Code                        | When                                                                                                                                      |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `PARTIAL_OPEN_PROGRESS`     | After each fill (floor + each retry). Payload: `cumulative_filled_making_amount`, `target_making_amount`, `filled_bps`, `attempt_number`. |
| `PARTIAL_OPEN_FLOOR_MISSED` | The floor FOK never filled; the position was reverted and fully refunded.                                                                 |

Use `PARTIAL_OPEN_PROGRESS` to drive a "filling… X%" indicator; treat `PARTIAL_OPEN_FLOOR_MISSED` as a terminal failure (order didn't fill, user refunded).

## Position display

The position shrinks to the actual fill, but the requested size is preserved separately:

* `origination_*` fields = the **full requested** size the user signed.
* `current_*` fields = the **actual filled** size the position opened at.

A 60% fill of a $60 request opens a \~$36 position. Render `current_*` as the live position; optionally show requested vs filled. Leverage is preserved across the shrink. The offer and position responses also echo `allow_partial_fill` and `min_fill_bps`.

## Errors

All partial-open validation happens at quote creation, before any order is placed:

| Code                              | Status | When                                                                                                                                                                                                         |
| --------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `quote_min_fill_bps_requires_fak` | 400    | `min_fill_bps` sent without `allow_partial_fill: true`.                                                                                                                                                      |
| `quote_min_fill_bps_out_of_range` | 400    | `min_fill_bps` outside `2000`–`5000`. Params: `min_fill_bps`, `absolute_min_bps`, `max_bps`.                                                                                                                 |
| `quote_min_fill_bps_step_invalid` | 400    | `min_fill_bps` not divisible by `500`. Params: `min_fill_bps`, `step_bps`.                                                                                                                                   |
| `quote_min_fill_bps_below_floor`  | 400    | `min_fill_bps` would shrink the position below the minimum collateral or notional. Params: `min_fill_bps`, `floor_min_fill_bps`, `bound_by`, `requested_collateral_usd_pips`, `requested_notional_usd_pips`. |
| `quote_fak_order_type_disabled`   | 403    | Partial-open temporarily disabled by a server kill switch. Omit `allow_partial_fill` for an atomic order.                                                                                                    |

See [Error Handling](/for-developers/api-and-events/error-handling.md#post-quotes) for the full quote-rejection table.
