# Tab payment completed

Webhook event: `tab.payment_completed`

Authoritative success signal for one payment, which may cover only part of the tab. It does not mean the tab was manually closed. Use tabSettled (or remainingBalanceCents) to decide whether the tab is fully paid, and use tab.closed only for manual or administrative closure.

Delivered payload:

```ts
{
  id: string // uuid
  event: "tab.payment_completed"
  resource: "tab"
  resourceId: string
  timestamp: string // date-time
  apiVersion: "v1"
  data: {
    customFields?: Array<{
        fieldId: string
        key: string
        label: string
        group: string
        type: string
        value: unknown
        displayValue: string
        version: integer
        status: string
      }>
    metadata?: Record<string, unknown>
    tab: {
      customFields?: { … }[]
      id: string // uuid
      metadata: Record<string, unknown>
    }
    location: {
      customFields?: { … }[]
      id: integer
      metadata: Record<string, unknown>
    }
    tabSettlementId: string | null
    purchaseIntentId: string // uuid
    paymentMethod: "prepaid" | "invoice" | "swish" | "terminal" | "online" | "gift_card" | "unknown"
    paymentMode: "ITEM" | "AMOUNT" | "INSTANT_PAY"
    amountCents: integer
    tabState?: string
    remainingBalanceCents?: integer
    tabSettled?: boolean
    pspReference?: string
    items?: Array<{
        kitchenDispatchItemId: string // uuid
        item: …
      }>
    itemCount?: integer
    surplusItemCount?: integer
    surplusAmountCents?: integer
    completedAt: string // date-time
  }
}
```
