# Gift Cards

Gift card issuance, balance, and redemption

## GET /api/v1/gift-cards

List gift cards

List gift cards with optional filters and pagination

**Permissions:** 🔵 `gift-cards.read`

Query parameters:
- `location_id` (number, optional) — Filter by location ID
- `include_children` (boolean, optional) — Include authorized descendants of location_id.
- `location_ids` (string, optional) — Optional comma-separated subset of the resolved location hierarchy.
- `status` ("active" | "redeemed" | "expired" | "frozen" | "cancelled", optional) — Filter by status
- `code` (string, optional) — Exact code match (case-insensitive)
- `loyalty_member_id` (number, optional) — Filter by loyalty member ID
- `page` (number, optional)
- `limit` (number, optional)
- `sort` ("created_at" | "valid_end_date" | "balance_cents" | "status" | "code", optional)
- `order` ("ASC" | "DESC", optional)

Response 200 — Paginated list of gift cards

```ts
{
  status?: "success"
  data?: {
    giftCards?: Array<{
        id?: string // uuid
        locationId?: number
        companyId?: number
        code?: string
        status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
        balanceCents?: number
        initialBalanceCents?: number
        currency?: string
        voucherClassification?: "enfunktion" | "flerfunktion"
        validStartDate?: string // date-time
        validEndDate?: string // date-time
        designId?: string | null // uuid
        loyaltyMemberId?: number | null
        recipientName?: string | null
        recipientEmail?: string | null
        recipientPhone?: string | null
        senderName?: string | null
        senderEmail?: string | null
        purchaserUserId?: number | null
        recipientAddress?: { … } | null
        emailLanguage?: string | null
        personalMessage?: string | null
        sourcePurchaseLineItemId?: number | null
        createdAt?: string // date-time
        updatedAt?: string // date-time
        isInherited?: boolean
        issuingLocationName?: string
      }>
    pagination?: {
      page?: number
      limit?: number
      total?: number
      totalPages?: number
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards

Create gift card

Create a new gift card with initial balance

**Permissions:** 🟢 `gift-cards.create`

Request body:

```ts
{
  locationId: integer
  companyId?: integer
  code?: string
  initialBalanceCents: integer
  currency?: string
  voucherClassification?: "enfunktion" | "flerfunktion"
  validStartDate?: string // date
  validEndDate?: string // date
  designId?: string // uuid
  loyaltyMemberId?: number
  recipientName?: string
  recipientEmail?: string // email
  recipientPhone?: string
  senderName?: string
  senderEmail?: string // email
  personalMessage?: string
  sourcePurchaseLineItemId?: number
  sendEmail?: boolean
}
```

Response 201 — Gift card created successfully

```ts
{
  status?: "success"
  data?: {
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    }
    transaction?: {
      id?: number
      giftCardId?: string // uuid
      type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
      amountCents?: number
      balanceAfterCents?: number
      referenceType?: string | null
      referenceId?: string | null
      notes?: string | null
      actorType?: string | null
      actorId?: string | null
      createdAt?: string // date-time
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## GET /api/v1/gift-cards/{id}

Get gift card

Get a gift card by UUID with full transaction history

**Permissions:** 🔵 `gift-cards.read`

Path parameters:
- `id` (string, required) — Gift card UUID

Response 200 — Gift card with transactions

```ts
{
  status?: "success"
  data?: {
    id?: string // uuid
    locationId?: number
    companyId?: number
    code?: string
    status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
    balanceCents?: number
    initialBalanceCents?: number
    currency?: string
    voucherClassification?: "enfunktion" | "flerfunktion"
    validStartDate?: string // date-time
    validEndDate?: string // date-time
    designId?: string | null // uuid
    loyaltyMemberId?: number | null
    recipientName?: string | null
    recipientEmail?: string | null
    recipientPhone?: string | null
    senderName?: string | null
    senderEmail?: string | null
    purchaserUserId?: number | null
    recipientAddress?: Record<string, unknown> | null
    emailLanguage?: string | null
    personalMessage?: string | null
    sourcePurchaseLineItemId?: number | null
    createdAt?: string // date-time
    updatedAt?: string // date-time
    isInherited?: boolean
    issuingLocationName?: string
    transactions?: Array<{
        id?: number
        giftCardId?: string // uuid
        type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
        amountCents?: number
        balanceAfterCents?: number
        referenceType?: string | null
        referenceId?: string | null
        notes?: string | null
        actorType?: string | null
        actorId?: string | null
        createdAt?: string // date-time
      }>
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## DELETE /api/v1/gift-cards/{id}

Invalidate gift card

Permanently cancel a gift card while retaining its balance and immutable audit history

**Permissions:** 🔴 `gift-cards.delete`

Path parameters:
- `id` (string, required)

Request body:

```ts
{
  reason: string
}
```

Response 200 — Updated gift card and audit transaction

```ts
{
  status?: "success"
  data?: {
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    }
    transaction?: {
      id?: number
      giftCardId?: string // uuid
      type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
      amountCents?: number
      balanceAfterCents?: number
      referenceType?: string | null
      referenceId?: string | null
      notes?: string | null
      actorType?: string | null
      actorId?: string | null
      createdAt?: string // date-time
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## PATCH /api/v1/gift-cards/{id}

Update gift card

Update allowed fields on a gift card (not balance)

**Permissions:** 🟠 `gift-cards.update`

Path parameters:
- `id` (string, required) — Gift card UUID

Request body:

```ts
{
  code?: string
  reason?: string
  designId?: string | null // uuid
  loyaltyMemberId?: number | null
  recipientName?: string | null
  recipientEmail?: string | null // email
  recipientPhone?: string | null
  recipientAddress?: Record<string, unknown> | null
  senderName?: string | null
  senderEmail?: string | null // email
  personalMessage?: string | null
  emailLanguage?: "en" | "sv"
  validEndDate?: string // date
}
```

Response 200 — Updated gift card

```ts
{
  status?: "success"
  data?: {
    id?: string // uuid
    locationId?: number
    companyId?: number
    code?: string
    status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
    balanceCents?: number
    initialBalanceCents?: number
    currency?: string
    voucherClassification?: "enfunktion" | "flerfunktion"
    validStartDate?: string // date-time
    validEndDate?: string // date-time
    designId?: string | null // uuid
    loyaltyMemberId?: number | null
    recipientName?: string | null
    recipientEmail?: string | null
    recipientPhone?: string | null
    senderName?: string | null
    senderEmail?: string | null
    purchaserUserId?: number | null
    recipientAddress?: Record<string, unknown> | null
    emailLanguage?: string | null
    personalMessage?: string | null
    sourcePurchaseLineItemId?: number | null
    createdAt?: string // date-time
    updatedAt?: string // date-time
    isInherited?: boolean
    issuingLocationName?: string
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/{id}/add-balance

Add gift card balance

Atomically increase a gift card balance with an audit reason

**Permissions:** ⚪ `gift-cards.increase`

Path parameters:
- `id` (string, required) — Gift card UUID

Request body:

```ts
{
  amountCents: integer
  referenceId?: string
  reason: string
  expectedBalanceCents?: integer
}
```

Response 200 — Refill result with updated gift card and transaction record

```ts
{
  status?: "success"
  data?: {
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    }
    transaction?: {
      id?: number
      giftCardId?: string // uuid
      type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
      amountCents?: number
      balanceAfterCents?: number
      referenceType?: string | null
      referenceId?: string | null
      notes?: string | null
      actorType?: string | null
      actorId?: string | null
      createdAt?: string // date-time
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## GET /api/v1/gift-cards/{id}/audit

Get gift card audit history

Read field changes and email resend requests for a gift card

**Permissions:** 🔵 `gift-cards.read`

Query parameters:
- `page` (integer, optional)
- `limit` (integer, optional)

Path parameters:
- `id` (string, required)

Response 200 — Default Response

```ts
{
  status?: string
  data?: {
    events?: Array<{
        id?: string
        giftCardId?: string
        action?: string
        changes?: { … }
        actorType?: string | null
        actorId?: string | null
        actor?: { … } | null
        requestId?: string | null
        reason?: string | null
        createdAt?: string // date-time
      }>
    pagination?: {
      page?: number
      limit?: number
      total?: number
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/{id}/deduct

Deduct gift card balance

Atomically reduce a gift card balance with an audit reason

**Permissions:** ⚪ `gift-cards.reduce`

Path parameters:
- `id` (string, required) — Gift card UUID

Request body:

```ts
{
  amountCents: integer
  referenceId?: string
  reason: string
  expectedBalanceCents?: integer
}
```

Response 200 — Deduction result with updated gift card and transaction record

```ts
{
  status?: "success"
  data?: {
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    }
    transaction?: {
      id?: number
      giftCardId?: string // uuid
      type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
      amountCents?: number
      balanceAfterCents?: number
      referenceType?: string | null
      referenceId?: string | null
      notes?: string | null
      actorType?: string | null
      actorId?: string | null
      createdAt?: string // date-time
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/{id}/freeze

Freeze gift card

Temporarily prevent a gift card from being redeemed

**Permissions:** ⚪ `gift-cards.freeze`

Path parameters:
- `id` (string, required)

Request body:

```ts
{
  reason: string
}
```

Response 200 — Updated gift card and audit transaction

```ts
{
  status?: "success"
  data?: {
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    }
    transaction?: {
      id?: number
      giftCardId?: string // uuid
      type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
      amountCents?: number
      balanceAfterCents?: number
      referenceType?: string | null
      referenceId?: string | null
      notes?: string | null
      actorType?: string | null
      actorId?: string | null
      createdAt?: string // date-time
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/{id}/link-loyalty

Link gift card to loyalty member

Link a gift card to a loyalty member by user ID. Fails with 409 if already linked to a different user.

**Permissions:** 🟠 `gift-cards.update`

Path parameters:
- `id` (string, required) — Gift card UUID

Request body:

```ts
{
  userId: number
}
```

Response 200 — Gift card linked successfully

```ts
{
  status?: "success"
  data?: {
    id?: string // uuid
    locationId?: number
    companyId?: number
    code?: string
    status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
    balanceCents?: number
    initialBalanceCents?: number
    currency?: string
    voucherClassification?: "enfunktion" | "flerfunktion"
    validStartDate?: string // date-time
    validEndDate?: string // date-time
    designId?: string | null // uuid
    loyaltyMemberId?: number | null
    recipientName?: string | null
    recipientEmail?: string | null
    recipientPhone?: string | null
    senderName?: string | null
    senderEmail?: string | null
    purchaserUserId?: number | null
    recipientAddress?: Record<string, unknown> | null
    emailLanguage?: string | null
    personalMessage?: string | null
    sourcePurchaseLineItemId?: number | null
    createdAt?: string // date-time
    updatedAt?: string // date-time
    isInherited?: boolean
    issuingLocationName?: string
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## DELETE /api/v1/gift-cards/{id}/link-loyalty

Unlink gift card from loyalty member

Unlink a gift card from a loyalty member. Only succeeds if the card is linked to the specified user.

**Permissions:** 🟠 `gift-cards.update`

Path parameters:
- `id` (string, required) — Gift card UUID

Request body:

```ts
{
  userId: number
}
```

Response 200 — Gift card unlinked successfully

```ts
{
  status?: "success"
  data?: {
    id?: string // uuid
    locationId?: number
    companyId?: number
    code?: string
    status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
    balanceCents?: number
    initialBalanceCents?: number
    currency?: string
    voucherClassification?: "enfunktion" | "flerfunktion"
    validStartDate?: string // date-time
    validEndDate?: string // date-time
    designId?: string | null // uuid
    loyaltyMemberId?: number | null
    recipientName?: string | null
    recipientEmail?: string | null
    recipientPhone?: string | null
    senderName?: string | null
    senderEmail?: string | null
    purchaserUserId?: number | null
    recipientAddress?: Record<string, unknown> | null
    emailLanguage?: string | null
    personalMessage?: string | null
    sourcePurchaseLineItemId?: number | null
    createdAt?: string // date-time
    updatedAt?: string // date-time
    isInherited?: boolean
    issuingLocationName?: string
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/{id}/resend-email

Resend a gift card email

Queue a gift card email for the saved recipient and record the request

**Permissions:** 🟠 `gift-cards.update`

Path parameters:
- `id` (string, required)

Response 200 — Default Response

```ts
{
  status?: string
  data?: {
    queued?: boolean
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## GET /api/v1/gift-cards/{id}/transactions

Get gift card transactions

Get transaction history for a gift card

**Permissions:** 🔵 `gift-cards.read`

Path parameters:
- `id` (string, required) — Gift card UUID

Response 200 — Transaction history

```ts
{
  status?: "success"
  data?: {
    transactions?: Array<{
        id?: number
        giftCardId?: string // uuid
        type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
        amountCents?: number
        balanceAfterCents?: number
        referenceType?: string | null
        referenceId?: string | null
        notes?: string | null
        actorType?: string | null
        actorId?: string | null
        createdAt?: string // date-time
      }>
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/{id}/unfreeze

Unfreeze gift card

Allow a frozen gift card to be redeemed again

**Permissions:** ⚪ `gift-cards.freeze`

Path parameters:
- `id` (string, required)

Request body:

```ts
{
  reason: string
}
```

Response 200 — Updated gift card and audit transaction

```ts
{
  status?: "success"
  data?: {
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    }
    transaction?: {
      id?: number
      giftCardId?: string // uuid
      type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
      amountCents?: number
      balanceAfterCents?: number
      referenceType?: string | null
      referenceId?: string | null
      notes?: string | null
      actorType?: string | null
      actorId?: string | null
      createdAt?: string // date-time
    }
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## GET /api/v1/gift-cards/by-code

Get gift card by code

Resolve a gift card by code at the X-Location-ID issuing location

**Permissions:** 🔵 `gift-cards.read`

Query parameters:
- `code` (string, required) — Gift card code (case-insensitive)
- `issuerLocationId` (integer, optional)

Response 200 — Gift card details

```ts
{
  status?: "success"
  data?: {
    id?: string // uuid
    locationId?: number
    companyId?: number
    code?: string
    status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
    balanceCents?: number
    initialBalanceCents?: number
    currency?: string
    voucherClassification?: "enfunktion" | "flerfunktion"
    validStartDate?: string // date-time
    validEndDate?: string // date-time
    designId?: string | null // uuid
    loyaltyMemberId?: number | null
    recipientName?: string | null
    recipientEmail?: string | null
    recipientPhone?: string | null
    senderName?: string | null
    senderEmail?: string | null
    purchaserUserId?: number | null
    recipientAddress?: Record<string, unknown> | null
    emailLanguage?: string | null
    personalMessage?: string | null
    sourcePurchaseLineItemId?: number | null
    createdAt?: string // date-time
    updatedAt?: string // date-time
    isInherited?: boolean
    issuingLocationName?: string
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/lookup

Look up gift card by code

Resolve a gift card at the X-Location-ID issuing location without putting its bearer code in the request URL

**Permissions:** 🔵 `gift-cards.read`

Request body:

```ts
{
  code: string
  issuerLocationId?: integer
}
```

Response 200 — Gift card details with transaction history

```ts
{
  status?: "success"
  data?: {
    id?: string // uuid
    locationId?: number
    companyId?: number
    code?: string
    status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
    balanceCents?: number
    initialBalanceCents?: number
    currency?: string
    voucherClassification?: "enfunktion" | "flerfunktion"
    validStartDate?: string // date-time
    validEndDate?: string // date-time
    designId?: string | null // uuid
    loyaltyMemberId?: number | null
    recipientName?: string | null
    recipientEmail?: string | null
    recipientPhone?: string | null
    senderName?: string | null
    senderEmail?: string | null
    purchaserUserId?: number | null
    recipientAddress?: Record<string, unknown> | null
    emailLanguage?: string | null
    personalMessage?: string | null
    sourcePurchaseLineItemId?: number | null
    createdAt?: string // date-time
    updatedAt?: string // date-time
    isInherited?: boolean
    issuingLocationName?: string
    transactions?: Array<{
        id?: number
        giftCardId?: string // uuid
        type?: "create" | "spend" | "refill" | "expire" | "migrate" | "adjustment" | "freeze" | "unfreeze" | "invalidate"
        amountCents?: number
        balanceAfterCents?: number
        referenceType?: string | null
        referenceId?: string | null
        notes?: string | null
        actorType?: string | null
        actorId?: string | null
        createdAt?: string // date-time
      }>
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/redeemable-issuers


Request body:

```ts
{
  code: string
  locationId: integer
}
```

Response 200 — Default Response

## GET /api/v1/gift-cards/settings

Get gift card settings

Location-level defaults applied when gift cards are created. Location comes from X-Location-Id unless locationId is given.

**Permissions:** 🔵 `gift-cards.read`

Query parameters:
- `locationId` (number, optional) — Overrides the X-Location-Id header

Response 200 — Gift card settings for the location

```ts
{
  status?: "success"
  data?: {
    locationId?: number
    voucherClassification?: "enfunktion" | "flerfunktion"
    giftCardDefaultValidityDays?: number
    giftCardLiabilityAccount?: string
    giftCardDeliveryFeeAccount?: string
    giftCardPhysicalFeeAccount?: string
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## PUT /api/v1/gift-cards/settings

Update gift card settings

Update the location-level gift card defaults. Only newly created cards are affected — existing cards keep the valid_end_date stamped at creation. giftCardLiabilityAccount is read-only and is ignored if sent.

**Permissions:** 🟠 `gift-cards.update`

Request body:

```ts
{
  locationId?: number
  voucherClassification?: "enfunktion" | "flerfunktion"
  giftCardDefaultValidityDays?: integer
  giftCardDeliveryFeeAccount?: string
  giftCardPhysicalFeeAccount?: string
}
```

Response 200 — Updated gift card settings

```ts
{
  status?: "success"
  data?: {
    locationId?: number
    voucherClassification?: "enfunktion" | "flerfunktion"
    giftCardDefaultValidityDays?: number
    giftCardLiabilityAccount?: string
    giftCardDeliveryFeeAccount?: string
    giftCardPhysicalFeeAccount?: string
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## GET /api/v1/gift-cards/stats

Get gift card portfolio statistics

Get issued, redeemed, outstanding, expired, and upcoming expiry values for a location portfolio.

**Permissions:** 🔵 `gift-cards.read`

Query parameters:
- `location_id` (number, optional) — Location ID; defaults to X-Location-Id
- `include_children` (boolean, optional) — Include authorized descendants of location_id.
- `location_ids` (string, optional) — Optional comma-separated subset of the resolved location hierarchy.

Response 200 — Gift card portfolio statistics

```ts
{
  status?: "success"
  data?: {
    totalLiabilityCents?: number
    totalCards?: number
    activeCards?: number
    fullyRedeemedCards?: number
    expiredCards?: number
    totalIssuedCents?: number
    totalRedeemedCents?: number
    totalRefilledCents?: number
    totalExpiredCents?: number
    avgBalanceCents?: number
    avgInitialValueCents?: number
    redemptionRate?: number
    expiredRate?: number
    expiring?: {
      days30?: {
        count?: number
        valueCents?: number
      }
      days90?: {
        count?: number
        valueCents?: number
      }
      days365?: {
        count?: number
        valueCents?: number
      }
    }
    last30Days?: {
      cardsCreated?: number
      cardsRedeemed?: number
      issuedCents?: number
      redeemedCents?: number
    }
    monthlyFlow?: Array<{
        month?: string
        issuedCents?: number
        redeemedCents?: number
        expiredCents?: number
      }>
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```

## POST /api/v1/gift-cards/validate

Validate gift card for payment

Validate a gift card code for payment use

**Permissions:** 🔵 `gift-cards.read`

Request body:

```ts
{
  code: string
  locationId: number
  issuerLocationId?: integer
}
```

Response 200 — Validation result

```ts
{
  status?: "success"
  data?: {
    valid?: boolean
    reason?: string | null
    giftCard?: {
      id?: string // uuid
      locationId?: number
      companyId?: number
      code?: string
      status?: "active" | "redeemed" | "expired" | "frozen" | "cancelled"
      balanceCents?: number
      initialBalanceCents?: number
      currency?: string
      voucherClassification?: "enfunktion" | "flerfunktion"
      validStartDate?: string // date-time
      validEndDate?: string // date-time
      designId?: string | null // uuid
      loyaltyMemberId?: number | null
      recipientName?: string | null
      recipientEmail?: string | null
      recipientPhone?: string | null
      senderName?: string | null
      senderEmail?: string | null
      purchaserUserId?: number | null
      recipientAddress?: Record<string, unknown> | null
      emailLanguage?: string | null
      personalMessage?: string | null
      sourcePurchaseLineItemId?: number | null
      createdAt?: string // date-time
      updatedAt?: string // date-time
      isInherited?: boolean
      issuingLocationName?: string
    } | null
  }
  meta?: {
    requestId?: string
    timestamp?: string // date-time
    executionTimeMs?: number
  }
}
```
