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

# Holds

> Reserve money before you know where it goes.

A hold reserves an amount on one account. `available` drops at once and `posted` does not move. Holds need the `holds:write` scope.

```bash theme={null}
curl -X POST "$PANOQORE_URL/v1/holds" \
  -H "Authorization: Bearer $PANOQORE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"accountId":"'"$WALLET"'","amount":"100000","currency":"NGN","reason":"Payout to bank","expiresAt":"2027-01-01T00:00:00Z"}'
```

A wallet with 500,000 then reads:

```json theme={null}
{ "posted": "500000", "pending": "100000", "available": "400000" }
```

## Ending a hold

**Capture** posts some or all of it. `credits` says where the value goes, and the debit leg on the held account is added for you. Leave `amount` out to capture everything still held.

```bash theme={null}
curl -X POST "$PANOQORE_URL/v1/holds/$HOLD/capture" \
  -H "Authorization: Bearer $PANOQORE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"amount":"40000","kind":"PAYOUT","externalRef":"payout-9","credits":[{"accountId":"'"$SETTLEMENT"'","side":"CREDIT","amount":"40000","currency":"NGN"}]}'
```

After a partial capture the hold stays `ACTIVE` with `captured: "40000"`, and the rest stays reserved. When all of it is captured, the status becomes `CAPTURED`.

**Release** gives back what is still held, and the status becomes `RELEASED`.

**Expiry** happens by itself once `expiresAt` passes: the status becomes `EXPIRED` and the money is back. A hold without `expiresAt` stays until you end it.

## A hold behind a pending entry

For a payout whose final legs you already know, protect a pending entry with the hold, by giving `holdId`. The hold's reservation covers the debit, so it is not counted twice.

```bash theme={null}
curl -X POST "$PANOQORE_URL/v1/entries" \
  -H "Authorization: Bearer $PANOQORE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "PAYOUT", "pending": true, "holdId": "'"$HOLD"'", "externalRef": "payout-10",
    "postings": [
      {"accountId": "'"$WALLET"'",     "side": "DEBIT",  "amount": "50000", "currency": "NGN"},
      {"accountId": "'"$SETTLEMENT"'", "side": "CREDIT", "amount": "50000", "currency": "NGN"}
    ]
  }'
```

From then on, the entry is in charge of the hold.

| Call | Entry | Hold |
| - | - | - |
| Post the entry | `POSTED` | `CAPTURED` |
| Void the entry | `VOIDED` | `RELEASED` |
| Hold expires | `VOIDED` | `EXPIRED` |

Capturing or releasing such a hold directly gets `HOLD_IN_USE`, with the entry in `details.entry_id`. `holdId` needs `"pending": true`.


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