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

# Purchase Events

> JSON Schema for the purchase loaded event.

<Warning>
  **Constraints**

  Purchase Loaded is published only for purchases performed by an identified customer.

  A purchase that fails business validation is still stored and emits the event with `WithFailedValidation: true`. On those events `StoreId`, product ids, names and categories can be null, and `Products` and `PaymentMethods` can be empty. Such events are not routed to downstream processing.
</Warning>

Published when a purchase has been loaded into Lobyco. The payload carries the receipt exactly as the Purchase API accepted it, before any Lobyco-side enrichment. `EventId` is composed as `PurchaseLoadedEvent-{ReceiptId}` and is stable across redeliveries, so use it for idempotent processing.

## Field reference

Field definitions match the purchase model accepted by the Purchase API. See [Purchases](/api-reference/retail-master-data/purchases) in the API Reference, and the [Transaction Data](/integration/pos-point-of-sale-integrations/transaction-data) guide for how purchases reach Lobyco and the validation rules.

| Event           | Triggering endpoint                  |
| --------------- | ------------------------------------ |
| Purchase Loaded | `POST /v1/purchases` — Load purchase |

## Schema

```json theme={"system"}
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "PurchaseLoaded",
  "description": "Published when a purchase performed by an identified member has been loaded into Lobyco. Carries the receipt exactly as it was accepted by the Purchase Load API, before any Lobyco-side enrichment.",
  "type": "object",
  "properties": {
    "MemberId": {
      "description": "Id of the member who performed the purchase.",
      "type": "string"
    },
    "CustomerId": {
      "description": "Same value as MemberId. Present on every customer-scoped Lobyco event.",
      "type": "string"
    },
    "EventId": {
      "description": "Identifier of this event occurrence, composed as 'PurchaseLoadedEvent-{ReceiptId}'. Stable across redeliveries, so it can be used for idempotent processing.",
      "type": "string"
    },
    "ReceiptId": {
      "description": "Globally unique purchase id, as supplied by the client.",
      "type": "string"
    },
    "StoreId": {
      "description": "Id of the store where the payment was made. Null only on events flagged with WithFailedValidation, which are stored without passing validation.",
      "type": ["string", "null"]
    },
    "ExternalDiscountCardId": {
      "description": "Identifier of an external discount card that is not linked to the loyalty app. When populated, bonus calculation is skipped because the customer already received external benefits.",
      "type": ["string", "null"]
    },
    "OrderId": {
      "description": "Order identifier the partial receipt was generated within. Related to e-commerce transactions.",
      "type": ["string", "null"]
    },
    "TotalAmount": {
      "description": "Total price of the purchased products with discounts and taxes applied. Can be negative when the total price of returned items exceeds the total price of purchased items.",
      "type": "number"
    },
    "AmountForBonusCalculation": {
      "description": "Total amount used for calculating bonuses, excluding ineligible items such as lottery, tobacco and alcohol products. Null when the client did not supply it and Lobyco excludes ineligible products itself.",
      "type": ["number", "null"]
    },
    "TotalTaxAmount": {
      "description": "Total amount of taxes (VAT) included in the price. Included in TotalAmount.",
      "type": "number"
    },
    "PurchaseDateTimeUtc": {
      "description": "Date and time of the purchase, in UTC.",
      "type": "string",
      "format": "date-time"
    },
    "PurchaseBusinessDateTime": {
      "description": "Date and time of the purchase in the store's local timezone.",
      "type": "string",
      "format": "date-time"
    },
    "Products": {
      "description": "The list of purchased products. Always present, and non-empty except on events flagged with WithFailedValidation.",
      "type": "array",
      "items": { "$ref": "#/$defs/product" }
    },
    "Discounts": {
      "description": "Discounts applied to individual products or to the whole purchase. Empty when no discounts were applied.",
      "type": "array",
      "items": { "$ref": "#/$defs/discount" }
    },
    "Shipping": {
      "description": "Shipping details. Null for purchases that are not shipped.",
      "$ref": "#/$defs/shippingInfo"
    },
    "PaymentMethods": {
      "description": "All payment methods the customer used to cover the purchase. Empty when TotalAmount is zero, or on events flagged with WithFailedValidation.",
      "type": "array",
      "items": { "$ref": "#/$defs/paymentMethod" }
    },
    "Taxes": {
      "description": "Summarised tax details for the whole purchase.",
      "type": "array",
      "items": { "$ref": "#/$defs/tax" }
    },
    "Metadata": {
      "description": "Client-specific key-value pairs attached to the purchase. Populated only when agreed during integration.",
      "$ref": "#/$defs/metadata"
    },
    "CheckoutType": {
      "description": "Type of checkout the purchase was made through.",
      "type": ["string", "null"],
      "enum": ["Pos", "SelfCheckout", "ScanAndPay", "Online", null]
    },
    "WithFailedValidation": {
      "description": "True when the purchase was accepted despite failing business validation. Such events are not routed to downstream processing.",
      "type": ["boolean", "null"]
    }
  },
  "$defs": {
    "product": {
      "description": "A purchased product or set of products.",
      "type": "object",
      "properties": {
        "Id": {
          "description": "Unique product identifier. Null only on events flagged with WithFailedValidation.",
          "type": ["string", "null"]
        },
        "SequenceNumber": {
          "description": "Id of the product within the purchase. Referenced by Discounts.AppliedProducts and DiscountAllocations.DiscountSequenceNumber.",
          "type": "integer"
        },
        "Name": {
          "description": "Product name. Null only on events flagged with WithFailedValidation.",
          "type": ["string", "null"]
        },
        "CategoryId": {
          "description": "Product category identifier. Null only on events flagged with WithFailedValidation.",
          "type": ["string", "null"]
        },
        "OriginalReceiptId": {
          "description": "Identifier of the original purchase this product was bought in. Null for a regular sale.",
          "type": ["string", "null"]
        },
        "DisposalItem": {
          "description": "Attached disposal item that carries a separate price, for example a bottle deposit.",
          "$ref": "#/$defs/disposalItem"
        },
        "UnitPrice": {
          "description": "Price per unit before discount is applied.",
          "type": ["number", "null"]
        },
        "Quantity": {
          "description": "Product units quantity.",
          "$ref": "#/$defs/quantity"
        },
        "OriginalPrice": {
          "description": "Actual price paid before discount is applied. Negative for returned items.",
          "type": "number"
        },
        "Price": {
          "description": "Same as OriginalPrice, but with discounts applied.",
          "type": "number"
        },
        "IsReturned": {
          "description": "Whether the product is returned.",
          "type": ["boolean", "null"]
        },
        "IsCancelled": {
          "description": "Whether the product is cancelled.",
          "type": ["boolean", "null"]
        },
        "TaxIncludedInPrice": {
          "description": "Whether the tax amount is included in the product price.",
          "type": ["boolean", "null"]
        },
        "Taxes": {
          "description": "Taxes applied to the product.",
          "type": "array",
          "items": { "$ref": "#/$defs/tax" }
        },
        "Metadata": {
          "description": "Client-specific key-value pairs attached to the product.",
          "$ref": "#/$defs/metadata"
        },
        "DiscountAllocations": {
          "description": "How much of each purchase-level discount was allocated to this product.",
          "type": ["array", "null"],
          "items": { "$ref": "#/$defs/discountAllocation" }
        }
      }
    },
    "quantity": {
      "type": ["object", "null"],
      "properties": {
        "UnitOfMeasure": {
          "description": "Unit of measure, for example Kg, LTR, EA.",
          "type": ["string", "null"]
        },
        "Value": {
          "description": "Product units quantity value. Negative when the item is refunded.",
          "type": "number"
        }
      }
    },
    "disposalItem": {
      "description": "Additional disposal item that goes with a product and has a separate price, for example a bottle deposit.",
      "type": ["object", "null"],
      "properties": {
        "Name": {
          "description": "Description of the disposal item.",
          "type": ["string", "null"]
        },
        "UnitPrice": {
          "description": "Price per unit, including tax, before discount is applied.",
          "type": "number"
        },
        "Quantity": {
          "description": "Disposal item units quantity.",
          "$ref": "#/$defs/quantity"
        },
        "TotalAmount": {
          "description": "UnitPrice multiplied by Quantity, including tax, before discount is applied.",
          "type": "number"
        }
      }
    },
    "tax": {
      "description": "Tax applied to a product or to the whole purchase.",
      "type": "object",
      "properties": {
        "Type": {
          "description": "Type of the tax, for example VAT or GST.",
          "type": ["string", "null"]
        },
        "TaxableAmount": {
          "description": "The amount the tax is applied on.",
          "type": ["number", "null"]
        },
        "Amount": {
          "description": "The amount of tax calculated by applying the appropriate tax rules.",
          "type": "number"
        },
        "Percentage": {
          "description": "The share of the taxable amount collected as tax, in the range 0 to 1. For example 0.11.",
          "type": ["number", "null"]
        }
      }
    },
    "discount": {
      "description": "A discount applied either to a set of products or to the whole purchase.",
      "type": "object",
      "properties": {
        "SequenceNumber": {
          "description": "Id of the discount within the purchase. Referenced by Products.DiscountAllocations.",
          "type": ["integer", "null"]
        },
        "Name": {
          "description": "Discount name.",
          "type": ["string", "null"]
        },
        "TotalDiscountAmount": {
          "description": "Total discount for the set of products.",
          "type": "number"
        },
        "CouponIds": {
          "description": "Lobyco or external coupon ids, present when the discount is coupon-based.",
          "type": ["array", "null"],
          "items": { "type": "string" }
        },
        "AppliedProducts": {
          "description": "Sequence numbers of the products this discount applies to. Null or empty means the discount is global and applies to the whole purchase.",
          "type": ["array", "null"],
          "items": { "type": "integer" }
        },
        "Metadata": {
          "description": "Client-specific key-value pairs attached to the discount.",
          "$ref": "#/$defs/metadata"
        }
      }
    },
    "discountAllocation": {
      "description": "The part of a purchase-level discount allocated to a single product.",
      "type": "object",
      "properties": {
        "DiscountSequenceNumber": {
          "description": "SequenceNumber of the discount this allocation belongs to.",
          "type": "integer"
        },
        "DiscountAmount": {
          "description": "Amount of that discount allocated to the product.",
          "type": "number"
        }
      }
    },
    "shippingInfo": {
      "type": ["object", "null"],
      "properties": {
        "RefundAsBonus": {
          "description": "Whether the shipping amount is refunded as bonus.",
          "type": "boolean"
        },
        "TotalAmount": {
          "description": "Total shipping amount.",
          "type": "number"
        }
      }
    },
    "paymentMethod": {
      "description": "Detailed information on how the purchase was paid.",
      "type": "object",
      "properties": {
        "Amount": {
          "description": "Amount covered by this payment, expressed in CurrencyCode when that is set.",
          "type": "number"
        },
        "CurrencyCode": {
          "description": "Payment currency code, ISO-4217 three characters, for example DKK, ISK, EUR. Null or empty means the receipt-level currency.",
          "type": ["string", "null"]
        },
        "ConversionRate": {
          "description": "Conversion rate of the payment currency to the local store currency. Set when CurrencyCode differs from the local currency.",
          "type": ["number", "null"]
        },
        "PaymentType": {
          "description": "Type of the payment.",
          "type": "string",
          "enum": ["Card", "Cash", "LoyaltyApp", "Other"]
        },
        "CardPan": {
          "description": "Masked card number. Applicable only to the 'Card' payment type.",
          "type": ["string", "null"]
        },
        "Rounding": {
          "description": "Rounding applied to the payment amount. Applicable only to the 'Cash' payment type.",
          "type": ["number", "null"]
        },
        "DisplayName": {
          "description": "Payment method display name.",
          "type": ["string", "null"]
        },
        "Metadata": {
          "description": "Client-specific key-value pairs attached to the payment method.",
          "$ref": "#/$defs/metadata"
        }
      }
    },
    "metadata": {
      "description": "Set of client-specific key-value pairs. Values may be of any JSON type.",
      "type": ["object", "null"],
      "additionalProperties": true
    }
  }
}
```
