<!-- canonical: https://docs.costplus.io/docs/guides/auth-capture-void -->

> Manage payment authorization, capture, and void flows
Some payment methods support a two-step flow: first **authorize** (reserve funds), then **capture** (collect the funds) or **void** (release the reservation).

## Capture Modes

Set `capture_mode` on the order to control when funds are captured:

| Mode | Behavior |
|------|----------|
| `manual` | You explicitly capture when ready (e.g., after shipping). If you don't capture before the order expires, the authorization is **lost** and cannot be captured. |
| `delayed` | Funds are automatically captured at the moment the `expiration_period` elapses. |

```json title="POST /v1/orders/ (manual capture)"
{
  "currency": "EUR",
  "amount": 5000,
  "capture_mode": "manual",
  "return_url": "https://www.example.com",
  "webhook_url": "https://www.example.com/webhook",
  "transactions": [
    {
      "payment_method": "credit-card"
    }
  ]
}
```

> [!WARNING]
> With `manual` capture, you **must** capture before the order's expiration period ends. Once expired, the authorization is released and the funds cannot be captured. Set an appropriate `expiration_period` for your fulfillment timeline.

> [!TIP]
> You can set `capture_mode` at the order level **without** specifying `transactions`. The hosted payment page will then only show payment methods that support the specified capture mode.

### Checking Capturable Amounts

Before capturing, you can check how much is available for capture by requesting `amount_details`:

```bash
curl -u YOUR_API_KEY: \
  "https://api.costplus.online/v1/orders/{order_id}/?fields[]=amount_details"
```

The response includes an `amount_details` object:

```json
{
  "amount": 5000,
  "amount_details": {
    "capturable": 5000,
    "captured": 0,
    "refundable": 0,
    "refunded": 0,
    "voidable": 5000,
    "voided": 0
  }
}
```

## Order Lines

When using captures and voids by order line, use these types:

| Type | Description |
|------|-------------|
| `physical` | Physical product |
| `discount` | Discount amount |
| `shipping_fee` | Shipping cost |
| `sales_tax` | Sales tax |
| `digital` | Digital product |
| `gift_card` | Gift card |
| `store_credit` | Store credit |
| `surcharge` | Surcharge |

## Capturing Payments

### Capture by Order Line

```bash
POST /v1/orders/{id}/transactions/{transaction_id}/captures/orderlines
```

```json title="Request body"
{
  "description": "Shipping item #1",
  "order_line": {
    "merchant_order_line_id": "item-001",
    "quantity": 1
  }
}
```

### Capture by Amount

```bash
POST /v1/orders/{id}/transactions/{transaction_id}/captures/amount
```

```json title="Request body"
{
  "description": "Partial capture",
  "amount": 2500
}
```

## Voiding Payments

Void releases the authorized funds back to the customer.

### Void by Order Line

```bash
POST /v1/orders/{id}/transactions/{transaction_id}/voids/orderlines
```

```json title="Request body"
{
  "description": "Voiding item #2",
  "order_line": {
    "merchant_order_line_id": "item-002",
    "quantity": 1
  }
}
```

### Void by Amount

```bash
POST /v1/orders/{id}/transactions/{transaction_id}/voids/amount
```

```json title="Request body"
{
  "description": "Partial void",
  "amount": 1500
}
```

## Query Parameters

Add query parameters to include additional details in the response:

| Parameter | Description |
|-----------|-------------|
| `?fields[]=order_line_details` | Include order line breakdown |
| `?fields[]=amount_details` | Include amount breakdown |

## Optimistic Locking

Capture and void endpoints support **ETag-based optimistic locking** via the `if-match` header. This prevents race conditions when multiple systems attempt to capture the same transaction.

```bash title="Capture with optimistic locking"
curl -X POST https://api.costplus.online/v1/orders/{id}/transactions/{tid}/captures/amount \
  -u {api_key}: \
  -H "Content-Type: application/json" \
  -H "if-match: \"etag-value\"" \
  -d '{"description": "Capture", "amount": 2500}'
```

If the ETag doesn't match (the order was modified since you last fetched it), you'll receive a `412 Precondition Failed` response.

> [!WARNING]
> Cost+ supports **one capture per authorization**, and voids can only be processed **before** any capture. Plan your capture strategy accordingly.

## Related Endpoints

- [Capture by Amount](/api-reference/orders/captureByAmount) — capture a specific amount from an authorized order
- [Capture by Order Line](/api-reference/orders/captureByOrderLine) — capture specific order lines
- [Void by Amount](/api-reference/orders/voidByAmount) — void a specific amount from an authorized order
- [Void by Order Line](/api-reference/orders/voidByOrderLine) — void specific order lines
