Phoenix Wallet

Reservations

API endpoints for holding and releasing funds

Reservations place a hold on funds in a wallet without actually moving them. This is useful for authorization patterns where you need to ensure funds are available before completing a transaction.

Create Reservation

Hold funds in a wallet for a future transaction.

POST /reservations

Request Headers

HeaderRequiredDescription
AuthorizationYesBearer token
Content-TypeYesapplication/json
Idempotency-KeyYesUnique request identifier

Request Body

FieldTypeRequiredDescription
wallet_idstringYesWallet to reserve funds from
amountstringYesAmount to reserve (decimal string)
assetstringYesAsset type (e.g., POINTS, BONUS)
expires_atstringNoExpiration timestamp (ISO 8601, default: 15 minutes)
referencestringNoYour reference for this reservation
metadataobjectNoCustom key-value pairs
lot_selectionobjectNoConfigure which lots to hold

Lot Selection Options

FieldTypeDefaultDescription
lot_selection.strategystringfifoSelection strategy: fifo, lifo, expiring_first, specific
lot_selection.lot_idsarray-Specific lot IDs (required when strategy is specific)

Example Request

curl -X POST {{BASE_URL}}/reservations \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: {{IDEMPOTENCY_KEY}}" \
  -d '{
    "wallet_id": "wal_abc123def456",
    "amount": "75.00",
    "asset": "POINTS",
    "expires_at": "2024-01-15T12:00:00Z",
    "reference": "order_auth_789",
    "metadata": {
      "order_id": "ord_12345",
      "merchant": "coffee_shop"
    },
    "lot_selection": {
      "strategy": "expiring_first"
    }
  }'

Example Response

{
  "data": {
    "id": "rsv_abc123def456",
    "wallet_id": "wal_abc123def456",
    "amount": "75.00",
    "asset": "POINTS",
    "status": "active",
    "expires_at": "2024-01-15T12:00:00Z",
    "reference": "order_auth_789",
    "held_lots": [
      {
        "lot_id": "lot_xyz789abc123",
        "amount": "75.00"
      }
    ],
    "metadata": {
      "order_id": "ord_12345",
      "merchant": "coffee_shop"
    },
    "created_at": "2024-01-15T11:45:00Z"
  }
}

Error Codes

CodeDescription
WALLET_NOT_FOUNDWallet does not exist
WALLET_SUSPENDEDCannot reserve from a suspended wallet
INSUFFICIENT_BALANCEWallet has insufficient available funds
INVALID_AMOUNTAmount must be a positive decimal
INVALID_ASSETAsset type is not configured
INVALID_EXPIRYExpiration must be in the future
LOT_NOT_FOUNDSpecified lot does not exist
LOT_INSUFFICIENT_BALANCESpecified lot has insufficient balance
POLICY_VIOLATIONReservation violates wallet policies

Commit Reservation

Convert a reservation into an actual debit from the wallet.

POST /reservations/{{RESERVATION_ID}}/commit

Path Parameters

ParameterTypeDescription
reservation_idstringThe reservation ID

Request Body

FieldTypeRequiredDescription
amountstringNoAmount to commit (defaults to full reservation)
referencestringNoYour reference for the commit
metadataobjectNoAdditional metadata to merge

Example Request

curl -X POST {{BASE_URL}}/reservations/{{RESERVATION_ID}}/commit \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: {{IDEMPOTENCY_KEY}}" \
  -d '{
    "amount": "65.00",
    "reference": "order_complete_789",
    "metadata": {
      "final_amount": "65.00",
      "tip_included": false
    }
  }'

Example Response

{
  "data": {
    "id": "rsv_abc123def456",
    "wallet_id": "wal_abc123def456",
    "original_amount": "75.00",
    "committed_amount": "65.00",
    "released_amount": "10.00",
    "asset": "POINTS",
    "status": "committed",
    "reference": "order_complete_789",
    "debit_id": "dbt_pqr789stu012",
    "metadata": {
      "order_id": "ord_12345",
      "merchant": "coffee_shop",
      "final_amount": "65.00",
      "tip_included": false
    },
    "created_at": "2024-01-15T11:45:00Z",
    "committed_at": "2024-01-15T11:55:00Z"
  }
}

Partial Commits

When committing less than the reserved amount, the difference is automatically released back to the wallet's available balance.

Error Codes

CodeDescription
RESERVATION_NOT_FOUNDReservation does not exist
RESERVATION_EXPIREDReservation has expired
RESERVATION_ALREADY_COMMITTEDReservation was already committed
RESERVATION_ALREADY_RELEASEDReservation was already released
AMOUNT_EXCEEDS_RESERVATIONCommit amount exceeds reserved amount

Release Reservation

Cancel a reservation and return the held funds to available balance.

POST /reservations/{{RESERVATION_ID}}/release

Path Parameters

ParameterTypeDescription
reservation_idstringThe reservation ID

Request Body

FieldTypeRequiredDescription
reasonstringNoReason for releasing
metadataobjectNoAdditional metadata

Example Request

curl -X POST {{BASE_URL}}/reservations/{{RESERVATION_ID}}/release \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: {{IDEMPOTENCY_KEY}}" \
  -d '{
    "reason": "Order cancelled by customer",
    "metadata": {
      "cancelled_by": "user_12345"
    }
  }'

Example Response

{
  "data": {
    "id": "rsv_abc123def456",
    "wallet_id": "wal_abc123def456",
    "amount": "75.00",
    "asset": "POINTS",
    "status": "released",
    "release_reason": "Order cancelled by customer",
    "metadata": {
      "order_id": "ord_12345",
      "merchant": "coffee_shop",
      "cancelled_by": "user_12345"
    },
    "created_at": "2024-01-15T11:45:00Z",
    "released_at": "2024-01-15T11:50:00Z"
  }
}

Error Codes

CodeDescription
RESERVATION_NOT_FOUNDReservation does not exist
RESERVATION_ALREADY_COMMITTEDReservation was already committed
RESERVATION_ALREADY_RELEASEDReservation was already released

Get Reservation

Retrieve details of a specific reservation.

GET /reservations/{{RESERVATION_ID}}

Path Parameters

ParameterTypeDescription
reservation_idstringThe reservation ID

Example Request

curl -X GET {{BASE_URL}}/reservations/{{RESERVATION_ID}} \
  -H "Authorization: Bearer {{API_KEY}}"

Example Response

{
  "data": {
    "id": "rsv_abc123def456",
    "wallet_id": "wal_abc123def456",
    "amount": "75.00",
    "asset": "POINTS",
    "status": "active",
    "expires_at": "2024-01-15T12:00:00Z",
    "reference": "order_auth_789",
    "held_lots": [
      {
        "lot_id": "lot_xyz789abc123",
        "amount": "75.00"
      }
    ],
    "metadata": {
      "order_id": "ord_12345",
      "merchant": "coffee_shop"
    },
    "created_at": "2024-01-15T11:45:00Z"
  }
}

List Reservations

Retrieve reservations for a wallet.

GET /wallets/{{WALLET_ID}}/reservations

Path Parameters

ParameterTypeDescription
wallet_idstringThe wallet ID

Query Parameters

ParameterTypeDefaultDescription
limitinteger20Number of results (max 100)
cursorstring-Pagination cursor
statusstring-Filter by status: active, committed, released, expired
assetstring-Filter by asset type

Example Request

curl -X GET "{{BASE_URL}}/wallets/{{WALLET_ID}}/reservations?status=active" \
  -H "Authorization: Bearer {{API_KEY}}"

Example Response

{
  "data": [
    {
      "id": "rsv_abc123def456",
      "wallet_id": "wal_abc123def456",
      "amount": "75.00",
      "asset": "POINTS",
      "status": "active",
      "expires_at": "2024-01-15T12:00:00Z",
      "reference": "order_auth_789",
      "created_at": "2024-01-15T11:45:00Z"
    }
  ],
  "pagination": {
    "has_more": false,
    "next_cursor": null
  }
}

Extend Reservation

Extend the expiration time of an active reservation.

POST /reservations/{{RESERVATION_ID}}/extend

Path Parameters

ParameterTypeDescription
reservation_idstringThe reservation ID

Request Body

FieldTypeRequiredDescription
expires_atstringYesNew expiration timestamp (ISO 8601)

Example Request

curl -X POST {{BASE_URL}}/reservations/{{RESERVATION_ID}}/extend \
  -H "Authorization: Bearer {{API_KEY}}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: {{IDEMPOTENCY_KEY}}" \
  -d '{
    "expires_at": "2024-01-15T14:00:00Z"
  }'

Example Response

{
  "data": {
    "id": "rsv_abc123def456",
    "wallet_id": "wal_abc123def456",
    "amount": "75.00",
    "asset": "POINTS",
    "status": "active",
    "expires_at": "2024-01-15T14:00:00Z",
    "previous_expires_at": "2024-01-15T12:00:00Z",
    "created_at": "2024-01-15T11:45:00Z",
    "extended_at": "2024-01-15T11:50:00Z"
  }
}

Error Codes

CodeDescription
RESERVATION_NOT_FOUNDReservation does not exist
RESERVATION_NOT_ACTIVECan only extend active reservations
INVALID_EXPIRYNew expiration must be after current expiration
MAX_EXTENSION_EXCEEDEDReservation cannot be extended beyond maximum duration