Skip to main content

Overview

Payout Operations API provides administrative functions for processing store payout requests, managing payout workflows, reviewing payout statistics, and handling wallet balance adjustments. Location: convex/admins/payoutOperations.ts

Get Pending Payouts

Retrieves pending payout requests for admin review. Can filter by store or return all pending payouts. Returns enriched data including store details, wallet balances, and bank information.
storeId
Id<'stores'>
Filter payouts by a specific store
limit
number
Maximum number of records to return (default: 50)
const pendingPayouts = await convex.query(api.admins.payoutOperations.getPendingPayouts, {
  limit: 50
});
[
  {
    "_id": "p123456789",
    "_creationTime": 1700000000000,
    "storeId": "s123456789",
    "storeName": "Pizza Palace",
    "storeOwnerName": "Ahmed",
    "storeOwnerPhone": "+971501234567",
    "requestedAmount": 500.00,
    "processingFee": 5.00,
    "netAmount": 495.00,
    "bankDetails": {
      "IBAN": "AE070331234567890123456",
      "bankName": "Emirates NBD",
      "accountHolderName": "Ahmed Ali"
    },
    "status": "requested",
    "requestDate": 1700000000000,
    "approvedDate": null,
    "requestedBy": "store_owner_123",
    "currentWalletBalance": 1200.00,
    "totalEarnings": 5000.00,
    "totalOrders": 150
  }
]

Get Payout Statistics

Returns payout statistics for the admin dashboard, including pending/processing counts, completed totals for today and this month, average processing time, and top stores by payout volume.
dateRange
object
Optional date range filter with startDate and endDate (Unix timestamps in milliseconds)
const stats = await convex.query(api.admins.payoutOperations.getPayoutStatistics, {});
{
  "totalPendingRequests": 5,
  "totalPendingAmount": 2500.00,
  "totalProcessingRequests": 2,
  "totalProcessingAmount": 1000.00,
  "totalCompletedToday": 3,
  "totalCompletedTodayAmount": 1500.00,
  "totalCompletedThisMonth": 45,
  "totalCompletedThisMonthAmount": 22500.00,
  "averageProcessingTime": 12.5,
  "topStoresByPayouts": [
    {
      "storeId": "s123456789",
      "storeName": "Pizza Palace",
      "totalPayouts": 8,
      "totalAmount": 4000.00
    }
  ]
}
averageProcessingTime is measured in hours. topStoresByPayouts returns up to 10 stores sorted by total payout amount this month.

Approve Payout

Approves a payout request. The payout must be in requested status. Updates associated wallet transactions to completed.
payoutId
Id<'payouts'>
required
Payout request ID to approve
adminUserId
string
required
Admin user ID performing the action
adminNotes
string
Optional notes about the approval decision
await convex.mutation(api.admins.payoutOperations.approvePayout, {
  adminUserId: "admin_123",
  payoutId: "p123456789",
  adminNotes: "Approved after verification"
});

Reject Payout

Rejects a payout request and returns the requested amount to the store’s available wallet balance. The payout must be in requested status. Sets payout status to cancelled and wallet transactions to cancelled.
payoutId
Id<'payouts'>
required
Payout request ID to reject
adminUserId
string
required
Admin user ID performing the action
rejectionReason
string
required
Reason for rejecting the payout
adminNotes
string
Optional additional admin notes
await convex.mutation(api.admins.payoutOperations.rejectPayout, {
  adminUserId: "admin_123",
  payoutId: "p123456789",
  rejectionReason: "Bank details do not match trade license",
  adminNotes: "Store owner contacted to update bank info"
});

Mark Payout As Processing

Marks an approved payout as processing when the bank transfer has been initiated. The payout must be in approved status.
payoutId
Id<'payouts'>
required
Payout request ID
adminUserId
string
required
Admin user ID performing the action
processingMethod
string
required
Method used to process the payout: bank_transfer, manual, or third_party
transactionReference
string
Bank or third-party transaction reference number
adminNotes
string
Optional admin notes
await convex.mutation(api.admins.payoutOperations.markPayoutAsProcessing, {
  adminUserId: "admin_123",
  payoutId: "p123456789",
  processingMethod: "bank_transfer",
  transactionReference: "ENBD-TXN-20240115-001"
});

Complete Payout

Marks a processing payout as completed. Updates wallet statistics including total payouts and last payout date. The payout must be in processing status.
payoutId
Id<'payouts'>
required
Payout request ID
adminUserId
string
required
Admin user ID performing the action
transactionReference
string
Final transaction reference (overrides existing if provided)
adminNotes
string
Optional admin notes
await convex.mutation(api.admins.payoutOperations.completePayout, {
  adminUserId: "admin_123",
  payoutId: "p123456789",
  transactionReference: "TXN123456789"
});

Mark Payout As Failed

Marks an approved or processing payout as failed. Optionally restores the requested amount to the store’s available wallet balance.
payoutId
Id<'payouts'>
required
Payout request ID
adminUserId
string
required
Admin user ID performing the action
failureReason
string
required
Reason for the failure (e.g., invalid IBAN, bank rejection)
adminNotes
string
Optional admin notes
restoreBalance
boolean
Whether to restore the payout amount back to the store’s available balance (default: false)
await convex.mutation(api.admins.payoutOperations.markPayoutAsFailed, {
  adminUserId: "admin_123",
  payoutId: "p123456789",
  failureReason: "Bank rejected transfer - invalid IBAN",
  restoreBalance: true,
  adminNotes: "Store owner notified to update bank details"
});
When restoreBalance is true, the requested amount is returned to the store’s available balance and associated wallet transactions are marked as failed. Use this when the bank transfer was rejected and the funds should be made available again.

Adjust Wallet Balance

Manually adjusts a store’s wallet balance. Supports adding/deducting available balance, adding/deducting pending balance, or moving funds from pending to available. Records a wallet transaction for audit purposes.
storeId
Id<'stores'>
required
Store ID owning the wallet
walletId
Id<'storeWallets'>
required
Wallet ID to adjust
adjustmentType
string
required
Type of adjustment:
  • add_balance — Add to available balance (recorded as bonus transaction)
  • deduct_balance — Deduct from available balance (recorded as penalty transaction)
  • add_pending — Add to pending balance
  • deduct_pending — Deduct from pending balance
  • move_pending_to_available — Transfer amount from pending to available balance
amount
number
required
Adjustment amount (must be positive)
reason
string
required
Reason for the adjustment (recorded in transaction description)
adminUserId
string
required
Admin user ID performing the adjustment
adminNotes
string
Optional additional notes (stored in transaction metadata)
await convex.mutation(api.admins.payoutOperations.adjustWalletBalance, {
  storeId: "s123456789",
  walletId: "w123456789",
  adjustmentType: "add_balance",
  amount: 100.00,
  reason: "Compensation for platform error on order #1234",
  adminUserId: "admin_123",
  adminNotes: "Approved by operations manager"
});
All wallet adjustments are audited via wallet transactions. The move_pending_to_available type does not create a transaction record as it is a net-zero operation. Deductions will fail if the wallet has insufficient balance.