{
  "components" : {
    "schemas" : {
      "AddressCorrectionRequest" : {
        "properties" : {
          "city" : {
            "description" : "Absent or null keeps the stored city",
            "example" : "Berlin",
            "maxLength" : 100,
            "type" : "string"
          },
          "country" : {
            "description" : "ISO 3166-1 alpha-2. It cannot change: a different country answers 422 country_change_not_allowed",
            "example" : "DE",
            "type" : "string"
          },
          "postalCode" : {
            "description" : "Absent, null or empty keeps the stored postal code",
            "example" : "10117",
            "maxLength" : 20,
            "type" : "string"
          },
          "street" : {
            "description" : "Absent or null keeps the stored street",
            "example" : "Friedrichstraße 43",
            "maxLength" : 255,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "AddressRequest" : {
        "properties" : {
          "city" : {
            "description" : "The city or town",
            "example" : "Berlin",
            "maxLength" : 100,
            "type" : "string"
          },
          "country" : {
            "description" : "ISO 3166-1 alpha-2",
            "example" : "DE",
            "type" : "string"
          },
          "postalCode" : {
            "description" : "Required for countries that use postal codes, such as DE, FR, GB and US; optional elsewhere, IE included. Its format is not checked",
            "example" : "10117",
            "maxLength" : 20,
            "type" : "string"
          },
          "street" : {
            "description" : "Street, house number and any flat or floor",
            "example" : "Unter den Linden 1",
            "maxLength" : 255,
            "type" : "string"
          }
        },
        "required" : [ "city", "country", "street" ],
        "type" : "object"
      },
      "Author" : {
        "properties" : {
          "kind" : {
            "description" : "API_KEY, TENANT_ACCOUNT (the tenant's team), TENANT_CLIENT, BACKOFFICE_ACCOUNT (Luxorr) or SYSTEM",
            "enum" : [ "API_KEY", "TENANT_ACCOUNT", "TENANT_CLIENT", "BACKOFFICE_ACCOUNT", "SYSTEM" ],
            "type" : "string"
          },
          "name" : {
            "description" : "The key's or person's name; \"Luxorr\" for Luxorr's team",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "BrandResponse" : {
        "properties" : {
          "id" : {
            "description" : "Send it as brandId on an order or a personal-link batch",
            "format" : "uuid",
            "type" : "string"
          },
          "logoUrl" : {
            "description" : "Absolute URL of the logo, which opens without a key; null when none is set",
            "type" : "string"
          },
          "name" : {
            "example" : "Example Brand",
            "type" : "string"
          },
          "primaryColour" : {
            "description" : "Hex colour of the brand; null for the default",
            "example" : "#0B1F3A",
            "type" : "string"
          },
          "slug" : {
            "example" : "example-brand",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "CampaignPageResponse" : {
        "properties" : {
          "items" : {
            "items" : {
              "$ref" : "#/components/schemas/PartnerCampaignSummary"
            },
            "type" : "array"
          },
          "nextCursor" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "CancelOrderRequest" : {
        "properties" : {
          "reason" : {
            "description" : "Why the order is cancelled",
            "example" : "Player self-excluded",
            "maxLength" : 1000,
            "type" : "string"
          }
        },
        "required" : [ "reason" ],
        "type" : "object"
      },
      "CancelRequest" : {
        "properties" : {
          "reason" : {
            "description" : "Why the link is withdrawn; never shown to the recipient",
            "example" : "Player self-excluded",
            "maxLength" : 1000,
            "type" : "string"
          }
        },
        "required" : [ "reason" ],
        "type" : "object"
      },
      "CategoryResponse" : {
        "properties" : {
          "code" : {
            "example" : "FOOD_DRINK",
            "type" : "string"
          },
          "name" : {
            "example" : "Food & Drink",
            "type" : "string"
          },
          "subcategories" : {
            "items" : {
              "$ref" : "#/components/schemas/SubcategoryResponse"
            },
            "type" : "array"
          }
        },
        "type" : "object"
      },
      "ClientRequest" : {
        "properties" : {
          "email" : {
            "description" : "Optional",
            "example" : "vip-desk@operator.example",
            "format" : "email",
            "maxLength" : 255,
            "type" : "string"
          },
          "name" : {
            "description" : "Who the gift is for, such as the player or the VIP desk ordering for them",
            "example" : "VIP desk",
            "maxLength" : 255,
            "type" : "string"
          }
        },
        "required" : [ "name" ],
        "type" : "object"
      },
      "CreateBatchRequest" : {
        "properties" : {
          "brandId" : {
            "description" : "With productIds, instead of campaignId: the brand the claim page wears",
            "format" : "uuid",
            "type" : "string"
          },
          "campaignId" : {
            "description" : "The campaign whose gifts the recipients choose from; or send brandId and productIds",
            "format" : "uuid",
            "type" : "string"
          },
          "productIds" : {
            "description" : "With brandId: the catalog gifts the recipients choose from",
            "items" : {
              "format" : "uuid",
              "type" : "string"
            },
            "type" : "array"
          },
          "recipients" : {
            "description" : "At most 1,000; each is validated on its own",
            "items" : {
              "$ref" : "#/components/schemas/PersonalLinkRecipient"
            },
            "maxItems" : 1000,
            "minItems" : 1,
            "type" : "array"
          }
        },
        "required" : [ "recipients" ],
        "type" : "object"
      },
      "CreateBatchResponse" : {
        "properties" : {
          "results" : {
            "items" : {
              "$ref" : "#/components/schemas/RecipientResultResponse"
            },
            "type" : "array"
          }
        },
        "type" : "object"
      },
      "CreateOrderRequest" : {
        "properties" : {
          "additionalDetails" : {
            "description" : "A note for Luxorr",
            "maxLength" : 2000,
            "type" : "string"
          },
          "afterHoursServiceAccepted" : {
            "description" : "The client accepts delivery work outside office hours; false when absent",
            "type" : "boolean"
          },
          "brandId" : {
            "description" : "The brand the gift is sent under. Required without campaignId; with one, leave it out or send the campaign's brand (else 422 brand_campaign_mismatch)",
            "format" : "uuid",
            "type" : "string"
          },
          "brandedPackagingRequested" : {
            "description" : "Pack the gift in the brand's packaging; false when absent",
            "type" : "boolean"
          },
          "campaignId" : {
            "description" : "Order from this campaign; the order takes the campaign's brand",
            "format" : "uuid",
            "type" : "string"
          },
          "client" : {
            "$ref" : "#/components/schemas/ClientRequest",
            "description" : "Who the gift is for"
          },
          "courierComment" : {
            "description" : "A note for the courier",
            "example" : "Ring twice",
            "maxLength" : 500,
            "type" : "string"
          },
          "customFields" : {
            "description" : "Answers to the tenant's own order fields. An answer whose fieldId names no field of the tenant is ignored",
            "items" : {
              "$ref" : "#/components/schemas/CustomFieldAnswerRequest"
            },
            "type" : "array"
          },
          "customization" : {
            "$ref" : "#/components/schemas/CustomizationRequest",
            "description" : "What to personalise; only for gifts with customizationAvailable"
          },
          "externalActionRef" : {
            "description" : "Your own action reference, for your reporting",
            "example" : "deposit-milestone-5",
            "maxLength" : 128,
            "type" : "string"
          },
          "externalCampaignRef" : {
            "description" : "Your own campaign reference, for your reporting",
            "example" : "vip-october",
            "maxLength" : 128,
            "type" : "string"
          },
          "externalOrderId" : {
            "description" : "Your own order ID, unique across the tenant. A second order with it answers 409 external_order_id_conflict",
            "example" : "ORD-1001",
            "maxLength" : 128,
            "type" : "string"
          },
          "externalRecipientId" : {
            "description" : "Your ID for the player; GET /orders filters by it",
            "example" : "player-77",
            "maxLength" : 128,
            "type" : "string"
          },
          "items" : {
            "description" : "Exactly one item: {productId, variations} for a catalog gift, or {customProductName, budget} for a custom request",
            "items" : {
              "$ref" : "#/components/schemas/ItemRequest"
            },
            "maxItems" : 1,
            "minItems" : 1,
            "type" : "array"
          },
          "managerEmail" : {
            "description" : "An active member of the tenant's team who then owns the order; unknown answers 422 manager_not_found",
            "example" : "vip-host@operator.example",
            "type" : "string"
          },
          "recipient" : {
            "$ref" : "#/components/schemas/RecipientRequest",
            "description" : "Where the gift ships"
          },
          "urgent" : {
            "description" : "Ask Luxorr to treat the order as urgent; false when absent",
            "type" : "boolean"
          }
        },
        "required" : [ "client", "externalOrderId", "items", "recipient" ],
        "type" : "object"
      },
      "CustomFieldAnswerRequest" : {
        "properties" : {
          "checked" : {
            "description" : "The answer to a checkbox field",
            "type" : "boolean"
          },
          "fieldId" : {
            "description" : "The tenant's custom field",
            "format" : "uuid",
            "type" : "string"
          },
          "textValue" : {
            "description" : "The answer to a text field, or the chosen option of a dropdown",
            "type" : "string"
          }
        },
        "required" : [ "fieldId" ],
        "type" : "object"
      },
      "CustomFieldRequest" : {
        "properties" : {
          "checked" : {
            "description" : "The answer to a checkbox field",
            "type" : "boolean"
          },
          "fieldId" : {
            "description" : "The tenant's custom field",
            "format" : "uuid",
            "type" : "string"
          },
          "textValue" : {
            "description" : "The answer to a text field, or the chosen option of a dropdown",
            "type" : "string"
          }
        },
        "required" : [ "fieldId" ],
        "type" : "object"
      },
      "CustomizationRequest" : {
        "properties" : {
          "details" : {
            "description" : "What to personalise",
            "maxLength" : 2000,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "EventListResponse" : {
        "properties" : {
          "items" : {
            "items" : {
              "$ref" : "#/components/schemas/PartnerEventEnvelope"
            },
            "type" : "array"
          },
          "nextCursor" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "Item" : {
        "properties" : {
          "kind" : {
            "description" : "CATALOG for a catalog gift, CUSTOM for a free-text request",
            "enum" : [ "CATALOG", "CUSTOM" ],
            "type" : "string"
          },
          "productId" : {
            "description" : "The catalog gift; null for a custom request",
            "format" : "uuid",
            "type" : "string"
          },
          "productName" : {
            "description" : "The gift's name, or the custom request's text",
            "type" : "string"
          },
          "variations" : {
            "additionalProperties" : {
              "type" : "string"
            },
            "description" : "The chosen value for each dimension of the gift",
            "type" : "object"
          }
        },
        "type" : "object"
      },
      "ItemRequest" : {
        "properties" : {
          "budget" : {
            "$ref" : "#/components/schemas/MoneyRequest",
            "description" : "Only with customProductName: the budget, in the tenant's currency"
          },
          "customProductName" : {
            "description" : "A free-text request instead of a catalog gift; cannot be combined with productId or campaignId",
            "example" : "Signed match jersey",
            "maxLength" : 255,
            "type" : "string"
          },
          "productId" : {
            "description" : "A catalog gift; leave it out for a custom request",
            "format" : "uuid",
            "type" : "string"
          },
          "variations" : {
            "additionalProperties" : {
              "type" : "string"
            },
            "description" : "One value for every dimension of the gift, as the catalog spells them",
            "example" : {
              "Colour" : "Black"
            },
            "type" : "object"
          }
        },
        "type" : "object"
      },
      "KeyResponse" : {
        "properties" : {
          "brandIds" : {
            "items" : {
              "format" : "uuid",
              "type" : "string"
            },
            "type" : "array"
          },
          "id" : {
            "format" : "int32",
            "type" : "integer"
          },
          "name" : {
            "type" : "string"
          },
          "prefix" : {
            "type" : "string"
          },
          "scopes" : {
            "items" : {
              "type" : "string"
            },
            "type" : "array"
          },
          "webhookUrl" : {
            "description" : "Where the key's events are sent; null when none is set",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "MeResponse" : {
        "properties" : {
          "environment" : {
            "type" : "string"
          },
          "key" : {
            "$ref" : "#/components/schemas/KeyResponse"
          },
          "tenant" : {
            "$ref" : "#/components/schemas/TenantResponse"
          }
        },
        "type" : "object"
      },
      "MessageSentResponse" : {
        "properties" : {
          "id" : {
            "format" : "uuid",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "MoneyRequest" : {
        "properties" : {
          "amount" : {
            "description" : "Positive, below 10000000000, at most 2 decimal places",
            "example" : "250.00",
            "type" : "number"
          },
          "currency" : {
            "description" : "The tenant's currency; another answers 400 naming the one expected",
            "example" : "EUR",
            "type" : "string"
          }
        },
        "required" : [ "amount", "currency" ],
        "type" : "object"
      },
      "OfferingResponse" : {
        "properties" : {
          "images" : {
            "description" : "The gift's images, as the product read returns them; they open without a key",
            "items" : {
              "$ref" : "#/components/schemas/PartnerImage"
            },
            "type" : "array"
          },
          "name" : {
            "description" : "The gift's name, in the locale asked for when it has a translation",
            "example" : "Cashmere scarf",
            "type" : "string"
          },
          "productId" : {
            "format" : "uuid",
            "type" : "string"
          },
          "skus" : {
            "items" : {
              "$ref" : "#/components/schemas/SkuResponse"
            },
            "type" : "array"
          },
          "status" : {
            "description" : "NEEDS_REVIEW while a catalog change has suspended the gift in this campaign",
            "enum" : [ "ACTIVE", "NEEDS_REVIEW" ],
            "type" : "string"
          },
          "supplyType" : {
            "description" : "STOCKED holds finite stock per SKU; ON_DEMAND is never limited",
            "enum" : [ "STOCKED", "ON_DEMAND" ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "OrderListResponse" : {
        "properties" : {
          "items" : {
            "items" : {
              "$ref" : "#/components/schemas/PartnerOrderRepresentation"
            },
            "type" : "array"
          },
          "nextCursor" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerCampaign" : {
        "properties" : {
          "brandId" : {
            "format" : "uuid",
            "type" : "string"
          },
          "expiresAt" : {
            "format" : "date-time",
            "type" : "string"
          },
          "id" : {
            "format" : "uuid",
            "type" : "string"
          },
          "name" : {
            "example" : "VIP birthdays",
            "type" : "string"
          },
          "offerings" : {
            "description" : "The campaign's gifts in display order",
            "items" : {
              "$ref" : "#/components/schemas/OfferingResponse"
            },
            "type" : "array"
          },
          "status" : {
            "enum" : [ "DRAFT", "ACTIVE", "COMPLETED" ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerCampaignSummary" : {
        "properties" : {
          "brandId" : {
            "format" : "uuid",
            "type" : "string"
          },
          "expiresAt" : {
            "description" : "When the campaign completes on its own; null when it never expires",
            "format" : "date-time",
            "type" : "string"
          },
          "id" : {
            "format" : "uuid",
            "type" : "string"
          },
          "name" : {
            "example" : "VIP birthdays",
            "type" : "string"
          },
          "status" : {
            "enum" : [ "DRAFT", "ACTIVE", "COMPLETED" ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerEventEnvelope" : {
        "properties" : {
          "data" : { },
          "environment" : {
            "type" : "string"
          },
          "id" : {
            "format" : "uuid",
            "type" : "string"
          },
          "occurredAt" : {
            "format" : "date-time",
            "type" : "string"
          },
          "type" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerImage" : {
        "properties" : {
          "url" : {
            "example" : "https://cdn.luxorr.io/k3/Qm/7Xp2Rt9Vb4Zn-x2.webp",
            "type" : "string"
          },
          "width" : {
            "description" : "Pixel width of this rendition; null when the original is served",
            "example" : 1000,
            "format" : "int32",
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PartnerMoney" : {
        "description" : "An amount as a decimal string with two places, and its ISO 4217 currency",
        "properties" : {
          "amount" : {
            "example" : "180.00",
            "type" : "string"
          },
          "currency" : {
            "example" : "EUR",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerOrderMessageRepresentation" : {
        "properties" : {
          "author" : {
            "$ref" : "#/components/schemas/Author"
          },
          "body" : {
            "description" : "The text",
            "type" : "string"
          },
          "createdAt" : {
            "description" : "When it was posted",
            "format" : "date-time",
            "type" : "string"
          },
          "id" : {
            "description" : "Luxorr's ID of the message",
            "format" : "uuid",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerOrderRepresentation" : {
        "properties" : {
          "brandId" : {
            "description" : "The brand the gift is sent under",
            "format" : "uuid",
            "type" : "string"
          },
          "campaignId" : {
            "description" : "The campaign it was ordered from; null for a catalog or custom order, and for an order claimed from a catalog-selection link",
            "format" : "uuid",
            "type" : "string"
          },
          "cancellationReason" : {
            "description" : "Why it was cancelled; null unless CANCELLED",
            "type" : "string"
          },
          "createdAt" : {
            "description" : "When the order was placed; UTC, with up to six decimal places",
            "format" : "date-time",
            "type" : "string"
          },
          "deliveryCountry" : {
            "description" : "ISO 3166-1 alpha-2. The only part of the address an order carries",
            "type" : "string"
          },
          "externalActionRef" : {
            "description" : "Your action reference, from the order or from the personal link it was claimed from",
            "type" : "string"
          },
          "externalCampaignRef" : {
            "description" : "Your campaign reference, from the order or from the personal link it was claimed from",
            "type" : "string"
          },
          "externalOrderId" : {
            "description" : "Your order ID; null for an order not placed through the API",
            "type" : "string"
          },
          "externalRecipientId" : {
            "description" : "Your ID for the player, from the order or from the personal link it was claimed from",
            "type" : "string"
          },
          "id" : {
            "description" : "Luxorr's ID of the order",
            "format" : "uuid",
            "type" : "string"
          },
          "items" : {
            "description" : "Always one item today",
            "items" : {
              "$ref" : "#/components/schemas/Item"
            },
            "type" : "array"
          },
          "personalLinkId" : {
            "description" : "The personal link whose claim placed it; null otherwise",
            "format" : "uuid",
            "type" : "string"
          },
          "receivedOutsideActiveHours" : {
            "description" : "The order arrived outside Luxorr's active hours, so work starts at the next opening",
            "type" : "boolean"
          },
          "reference" : {
            "description" : "Luxorr's human-readable reference; quote it when you talk to Luxorr",
            "type" : "string"
          },
          "selection" : {
            "description" : "CATALOG for an order claimed from a link sent with {brandId, productIds}; null otherwise",
            "enum" : [ "CATALOG" ],
            "type" : "string"
          },
          "shipments" : {
            "description" : "Empty until Luxorr dispatches the gift; at most one today",
            "items" : {
              "$ref" : "#/components/schemas/Shipment"
            },
            "type" : "array"
          },
          "source" : {
            "description" : "How the order came in: API, PERSONAL_LINK (a player claimed a link), WORKSPACE (the tenant's team) or BACKOFFICE (Luxorr)",
            "enum" : [ "API", "PERSONAL_LINK", "WORKSPACE", "BACKOFFICE" ],
            "type" : "string"
          },
          "status" : {
            "description" : "Where the order is; see the order lifecycle guide",
            "enum" : [ "REQUESTED", "PROCESSING", "SENT", "COMPLETED", "CANCELLED" ],
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "When the order last changed; UTC, with up to six decimal places. Pass the newest you hold, less a few minutes, as updatedSince",
            "format" : "date-time",
            "type" : "string"
          },
          "urgent" : {
            "description" : "Luxorr treats the order as urgent",
            "type" : "boolean"
          },
          "version" : {
            "description" : "0 when placed; grows with every change. Send it as expectedVersion to :update-delivery",
            "format" : "int64",
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "PartnerPersonalLinkRepresentation" : {
        "properties" : {
          "approvedAt" : {
            "description" : "When the tenant's team approved a link that started REQUESTED; null for a link that started ACTIVE, because the tenant requires no approval",
            "format" : "date-time",
            "type" : "string"
          },
          "brandId" : {
            "description" : "The brand the claim page wears",
            "format" : "uuid",
            "type" : "string"
          },
          "campaignId" : {
            "description" : "The campaign whose gifts the player chooses from; null for a link sent with {brandId, productIds}",
            "format" : "uuid",
            "type" : "string"
          },
          "cancelledAt" : {
            "description" : "When it was withdrawn; null unless CANCELLED",
            "format" : "date-time",
            "type" : "string"
          },
          "claimUrl" : {
            "description" : "The link to pass to the player",
            "type" : "string"
          },
          "claimedAt" : {
            "description" : "When the player claimed it; null until CLAIMED",
            "format" : "date-time",
            "type" : "string"
          },
          "createdAt" : {
            "description" : "When the link was created",
            "format" : "date-time",
            "type" : "string"
          },
          "externalRecipientId" : {
            "description" : "Your ID for the player, as sent in the batch",
            "type" : "string"
          },
          "id" : {
            "description" : "Luxorr's ID of the link",
            "format" : "uuid",
            "type" : "string"
          },
          "orderId" : {
            "description" : "The order the claim placed; null until CLAIMED",
            "format" : "uuid",
            "type" : "string"
          },
          "selection" : {
            "description" : "CATALOG for a link sent with {brandId, productIds}, whose gifts were picked from the catalog; null for a campaign link",
            "enum" : [ "CATALOG" ],
            "type" : "string"
          },
          "status" : {
            "description" : "Where the link is; see the personal links guide",
            "enum" : [ "REQUESTED", "ACTIVE", "CLAIMED", "EXPIRED", "CANCELLED" ],
            "type" : "string"
          },
          "updatedAt" : {
            "description" : "When the link last changed; pass the newest you hold, less a few minutes, as updatedSince",
            "format" : "date-time",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PartnerProduct" : {
        "properties" : {
          "available" : {
            "description" : "Whether the gift can be supplied to the requested country",
            "type" : "boolean"
          },
          "categories" : {
            "items" : {
              "example" : "FASHION__ACCESSORIES",
              "type" : "string"
            },
            "type" : "array"
          },
          "customizationAvailable" : {
            "type" : "boolean"
          },
          "description" : {
            "type" : "string"
          },
          "estimate" : {
            "$ref" : "#/components/schemas/PartnerMoney",
            "description" : "The estimate in the tenant's currency at today's catalog rate; null when unpriced"
          },
          "estimateEur" : {
            "$ref" : "#/components/schemas/PartnerMoney",
            "description" : "The estimate in EUR, the catalog's currency of record; null when unpriced"
          },
          "giftSet" : {
            "type" : "boolean"
          },
          "id" : {
            "format" : "uuid",
            "type" : "string"
          },
          "images" : {
            "items" : {
              "$ref" : "#/components/schemas/PartnerImage"
            },
            "type" : "array"
          },
          "listed" : {
            "description" : "Always true here; false only on the unlisted entries of an updatedSince read",
            "type" : "boolean"
          },
          "name" : {
            "example" : "Cashmere scarf",
            "type" : "string"
          },
          "priced" : {
            "description" : "Whether staff have priced the gift for the country's region",
            "type" : "boolean"
          },
          "readyToSend" : {
            "type" : "boolean"
          },
          "updatedAt" : {
            "example" : "2026-10-05T09:12:44Z",
            "format" : "date-time",
            "type" : "string"
          },
          "variations" : {
            "items" : {
              "$ref" : "#/components/schemas/VariationResponse"
            },
            "type" : "array"
          }
        },
        "type" : "object"
      },
      "PartnerUnlistedProduct" : {
        "description" : "A gift that left the catalog since updatedSince: unpublished, archived or made internal",
        "properties" : {
          "id" : {
            "format" : "uuid",
            "type" : "string"
          },
          "listed" : {
            "example" : false,
            "type" : "boolean"
          },
          "updatedAt" : {
            "example" : "2026-10-05T09:12:44Z",
            "format" : "date-time",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PersonalLinkPageResponse" : {
        "properties" : {
          "items" : {
            "items" : {
              "$ref" : "#/components/schemas/PartnerPersonalLinkRepresentation"
            },
            "type" : "array"
          },
          "nextCursor" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "PersonalLinkRecipient" : {
        "properties" : {
          "customFields" : {
            "description" : "Answers to the tenant's own fields. An answer whose fieldId names no field of the tenant is ignored",
            "items" : {
              "$ref" : "#/components/schemas/CustomFieldRequest"
            },
            "type" : "array"
          },
          "email" : {
            "description" : "Optional; once per batch",
            "example" : "ann@example.com",
            "format" : "email",
            "maxLength" : 255,
            "type" : "string"
          },
          "externalRecipientId" : {
            "description" : "Your own ID for the recipient",
            "example" : "player-1001",
            "maxLength" : 128,
            "type" : "string"
          },
          "label" : {
            "description" : "The recipient's name, shown on the claim page",
            "example" : "Ann Smith",
            "maxLength" : 255,
            "type" : "string"
          },
          "locale" : {
            "description" : "A locale the tenant has enabled, or en-US, which every tenant has; en-US when absent. Ask your Luxorr contact which locales are enabled",
            "example" : "en-US",
            "type" : "string"
          },
          "managerEmail" : {
            "description" : "An active team member who manages the link; unknown is a rejected recipient",
            "type" : "string"
          },
          "message" : {
            "description" : "A personal note shown on the claim page",
            "maxLength" : 255,
            "type" : "string"
          }
        },
        "required" : [ "label" ],
        "type" : "object"
      },
      "ProblemDetail" : {
        "description" : "An `application/problem+json` error. Branch on `code`; `detail` is for people.",
        "properties" : {
          "code" : {
            "description" : "Stable, snake_case",
            "example" : "not_cancellable",
            "type" : "string"
          },
          "currentStatus" : {
            "description" : "On `not_editable` and `not_cancellable`: the record's status now",
            "type" : "string"
          },
          "detail" : {
            "description" : "This occurrence, in English",
            "type" : "string"
          },
          "errors" : {
            "description" : "Validation failures, one per field",
            "items" : {
              "properties" : {
                "code" : {
                  "example" : "required",
                  "type" : "string"
                },
                "field" : {
                  "example" : "recipient.phone",
                  "type" : "string"
                },
                "message" : {
                  "type" : "string"
                }
              },
              "type" : "object"
            },
            "type" : "array"
          },
          "orderId" : {
            "description" : "On `external_order_id_conflict`: the existing order, when the key can see it",
            "format" : "uuid",
            "type" : "string"
          },
          "status" : {
            "description" : "The HTTP status",
            "format" : "int32",
            "type" : "integer"
          },
          "title" : {
            "description" : "A short label for the code",
            "type" : "string"
          },
          "type" : {
            "description" : "Links to the code on the docs site",
            "format" : "uri",
            "type" : "string"
          }
        },
        "required" : [ "code", "status", "title", "type" ],
        "type" : "object"
      },
      "ProductItemResponse" : {
        "oneOf" : [ {
          "$ref" : "#/components/schemas/PartnerProduct"
        }, {
          "$ref" : "#/components/schemas/PartnerUnlistedProduct"
        } ]
      },
      "ProductPageResponse" : {
        "properties" : {
          "items" : {
            "items" : {
              "$ref" : "#/components/schemas/ProductItemResponse"
            },
            "type" : "array"
          },
          "nextCursor" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "RecipientCorrectionRequest" : {
        "properties" : {
          "address" : {
            "$ref" : "#/components/schemas/AddressCorrectionRequest",
            "description" : "Only the address fields that change; absent keeps the stored address"
          },
          "email" : {
            "description" : "Absent, null or empty keeps the stored email",
            "example" : "wendy@example.com",
            "format" : "email",
            "maxLength" : 255,
            "type" : "string"
          },
          "name" : {
            "description" : "Absent or null keeps the stored name",
            "example" : "Wendy Player",
            "maxLength" : 100,
            "type" : "string"
          },
          "phone" : {
            "description" : "International format; absent or null keeps the stored phone",
            "example" : "+4930123456",
            "maxLength" : 50,
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "RecipientErrorResponse" : {
        "properties" : {
          "code" : {
            "example" : "invalid",
            "type" : "string"
          },
          "field" : {
            "example" : "email",
            "type" : "string"
          },
          "message" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "RecipientRequest" : {
        "properties" : {
          "address" : {
            "$ref" : "#/components/schemas/AddressRequest",
            "description" : "Where the parcel goes"
          },
          "email" : {
            "description" : "Optional",
            "example" : "wendy@example.com",
            "format" : "email",
            "maxLength" : 255,
            "type" : "string"
          },
          "name" : {
            "description" : "Who receives the parcel",
            "example" : "Wendy Player",
            "maxLength" : 100,
            "type" : "string"
          },
          "phone" : {
            "description" : "International format: + and the country code, then the number's digits",
            "example" : "+4930123456",
            "maxLength" : 50,
            "type" : "string"
          }
        },
        "required" : [ "address", "name", "phone" ],
        "type" : "object"
      },
      "RecipientResultResponse" : {
        "properties" : {
          "errors" : {
            "description" : "Present when REJECTED",
            "items" : {
              "$ref" : "#/components/schemas/RecipientErrorResponse"
            },
            "type" : "array"
          },
          "externalRecipientId" : {
            "type" : "string"
          },
          "index" : {
            "description" : "The recipient's 0-based position in the request",
            "format" : "int32",
            "type" : "integer"
          },
          "link" : {
            "$ref" : "#/components/schemas/PartnerPersonalLinkRepresentation",
            "description" : "Present when CREATED"
          },
          "outcome" : {
            "description" : "CREATED or REJECTED",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "SendMessageRequest" : {
        "properties" : {
          "body" : {
            "description" : "The message, as plain text; attachments are not accepted",
            "example" : "Could you confirm the delivery date?",
            "maxLength" : 4000,
            "type" : "string"
          }
        },
        "required" : [ "body" ],
        "type" : "object"
      },
      "Shipment" : {
        "properties" : {
          "carrier" : {
            "description" : "The carrier's name",
            "type" : "string"
          },
          "trackingReference" : {
            "description" : "The carrier's tracking number",
            "type" : "string"
          },
          "trackingUrl" : {
            "description" : "A link to follow the parcel",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "SkuResponse" : {
        "properties" : {
          "stockRemaining" : {
            "description" : "Units left; null for on-demand offerings",
            "example" : 12,
            "format" : "int32",
            "type" : "integer"
          },
          "variations" : {
            "additionalProperties" : {
              "type" : "string"
            },
            "description" : "The variation choice this SKU stands for, dimension to value",
            "type" : "object"
          }
        },
        "type" : "object"
      },
      "SubcategoryResponse" : {
        "properties" : {
          "code" : {
            "example" : "FOOD_DRINK__WINE_CHAMPAGNE",
            "type" : "string"
          },
          "name" : {
            "example" : "Wine & Champagne",
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "TenantCustomFieldResponse" : {
        "properties" : {
          "id" : {
            "description" : "The fieldId to answer it with",
            "format" : "uuid",
            "type" : "string"
          },
          "label" : {
            "type" : "string"
          },
          "options" : {
            "description" : "A dropdown's values; empty for any other type",
            "items" : {
              "type" : "string"
            },
            "type" : "array"
          },
          "required" : {
            "description" : "An order or personal link must answer it",
            "type" : "boolean"
          },
          "type" : {
            "enum" : [ "TEXT", "CHECKBOX", "DROPDOWN" ],
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "TenantResponse" : {
        "properties" : {
          "approvalRequired" : {
            "description" : "New orders and personal links wait for the tenant's approval, as REQUESTED",
            "type" : "boolean"
          },
          "currency" : {
            "description" : "ISO 4217. Catalog estimates are in it, and a custom order's budget must be",
            "example" : "EUR",
            "type" : "string"
          },
          "customFields" : {
            "description" : "The tenant's own order fields, in display order",
            "items" : {
              "$ref" : "#/components/schemas/TenantCustomFieldResponse"
            },
            "type" : "array"
          },
          "id" : {
            "format" : "uuid",
            "type" : "string"
          },
          "locales" : {
            "description" : "The languages a personal link accepts: en-US, which every tenant has, and the ones the tenant enabled",
            "example" : [ "en-US", "de-DE" ],
            "items" : {
              "type" : "string"
            },
            "type" : "array"
          },
          "name" : {
            "type" : "string"
          }
        },
        "type" : "object"
      },
      "TestEventResponse" : {
        "properties" : {
          "error" : {
            "type" : "string"
          },
          "responseStatus" : {
            "format" : "int32",
            "type" : "integer"
          }
        },
        "type" : "object"
      },
      "UpdateDeliveryRequest" : {
        "properties" : {
          "courierComment" : {
            "description" : "Absent keeps the stored comment",
            "maxLength" : 500,
            "type" : "string"
          },
          "expectedVersion" : {
            "description" : "The order's version as you last read it; another answers 409 version_conflict",
            "example" : 0,
            "format" : "int64",
            "type" : "integer"
          },
          "recipient" : {
            "$ref" : "#/components/schemas/RecipientCorrectionRequest",
            "description" : "Only the recipient fields that change: each one sent replaces the stored value, and the rest are kept; absent keeps the recipient as it is"
          },
          "urgent" : {
            "description" : "Absent keeps the stored urgency",
            "type" : "boolean"
          }
        },
        "required" : [ "expectedVersion" ],
        "type" : "object"
      },
      "VariationResponse" : {
        "properties" : {
          "dimension" : {
            "example" : "Colour",
            "type" : "string"
          },
          "values" : {
            "items" : {
              "example" : "Black",
              "type" : "string"
            },
            "type" : "array"
          }
        },
        "type" : "object"
      }
    },
    "securitySchemes" : {
      "apiKey" : {
        "bearerFormat" : "lxr_<live|sbx>_<random>",
        "description" : "The API key, sent as `Authorization: Bearer <key>`. A missing, malformed, unknown or revoked key answers 401 `invalid_api_key`; an endpoint outside the key's scopes answers 403 `insufficient_scope`.",
        "scheme" : "bearer",
        "type" : "http"
      }
    }
  },
  "info" : {
    "description" : "Catalog, orders, personal links and signed events for operators and platforms. Authenticate every call with `Authorization: Bearer <key>`; every POST needs an `Idempotency-Key` header. Guides: https://docs.luxorr.io",
    "title" : "Luxorr API",
    "version" : "v1"
  },
  "openapi" : "3.1.0",
  "paths" : {
    "/brands" : {
      "get" : {
        "description" : "The brands the key may act under. Not paged. A key limited to some brands sees only those. Any scope may read it.",
        "operationId" : "listBrands",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "items" : {
                    "$ref" : "#/components/schemas/BrandResponse"
                  },
                  "type" : "array"
                }
              }
            },
            "description" : "The brands"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List brands",
        "tags" : [ "Catalog" ]
      }
    },
    "/campaigns" : {
      "get" : {
        "description" : "Active and completed campaigns within the key's brands, paged by name. Campaigns still being prepared are not listed.",
        "operationId" : "listCampaigns",
        "parameters" : [ {
          "description" : "Only this brand's campaigns",
          "in" : "query",
          "name" : "brandId",
          "required" : false,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "ACTIVE or COMPLETED",
          "in" : "query",
          "name" : "status",
          "required" : false,
          "schema" : {
            "enum" : [ "ACTIVE", "COMPLETED" ],
            "type" : "string"
          }
        }, {
          "description" : "The nextCursor of the previous page",
          "in" : "query",
          "name" : "after",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Page size, 1 to 100; 25 when absent",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "default" : 25,
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CampaignPageResponse"
                }
              }
            },
            "description" : "A page of campaigns"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: an unreadable brandId, status, limit or cursor; errors[].field names it"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold CATALOG"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List campaigns",
        "tags" : [ "Campaigns" ]
      }
    },
    "/campaigns/{campaignId}" : {
      "get" : {
        "description" : "One campaign with its offerings, SKUs and remaining stock. A campaign of another tenant, outside the key's brands, still in preparation or unknown answers the same 404 not_found.",
        "operationId" : "getCampaign",
        "parameters" : [ {
          "in" : "path",
          "name" : "campaignId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A supported BCP 47 tag for the offerings' names",
          "in" : "query",
          "name" : "locale",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerCampaign"
                }
              }
            },
            "description" : "The campaign"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: locale malformed or not a supported locale; errors[].field names it"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold CATALOG"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no campaign with this id that the key can see"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Read a campaign",
        "tags" : [ "Campaigns" ]
      }
    },
    "/catalog/categories" : {
      "get" : {
        "description" : "Categories and their subcategories. A gift's categories are subcategory codes from this tree. Either level's code works as the category filter of the product list.",
        "operationId" : "listCatalogCategories",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "items" : {
                    "$ref" : "#/components/schemas/CategoryResponse"
                  },
                  "type" : "array"
                }
              }
            },
            "description" : "The category tree"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold CATALOG"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List categories",
        "tags" : [ "Catalog" ]
      }
    },
    "/catalog/images/{fileId}" : {
      "get" : {
        "description" : "A gift image or a brand logo. Needs no API key. The image URLs in catalog and brand responses point here when no CDN URL exists, so they open straight in a browser or an <img> tag. Only images of published, public gifts and brand logos are served; any other id answers 404 not_found. Responses are cacheable for a year: a replaced image gets a new id. Limited to 600 requests a minute per client IP.",
        "operationId" : "getCatalogImage",
        "parameters" : [ {
          "in" : "path",
          "name" : "fileId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Rendition to serve: x1 (500 px), x2 (1000 px) or x3 (1500 px); the original when absent",
          "in" : "query",
          "name" : "scale",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "image/*" : {
                "schema" : {
                  "format" : "binary",
                  "type" : "string"
                }
              }
            },
            "description" : "The image"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no servable image with this id"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 600 image requests a minute from this IP; see Retry-After"
          }
        },
        "security" : [ ],
        "summary" : "Read an image",
        "tags" : [ "Catalog" ]
      }
    },
    "/catalog/products" : {
      "get" : {
        "description" : "Without updatedSince: the published, public gifts available in the country, filtered by q, category and readyToSend, in name order. With updatedSince: every gift whose listing, price or availability changed at or after that instant, oldest change first (updatedAt, then id). country and locale still shape each gift, but q, category and readyToSend do not narrow the answer; an unknown country, locale or category code answers 400 either way. A gift that was unpublished, archived or made internal comes back as {id, listed: false, updatedAt}; drop it from your copy. For the next sync, pass the newest updatedAt you hold minus five minutes: a change still committing during your read can carry an earlier time. Reading a gift again is harmless; replace your copy with it.",
        "operationId" : "listProducts",
        "parameters" : [ {
          "description" : "Delivery country, ISO 3166-1 alpha-2",
          "example" : "DE",
          "in" : "query",
          "name" : "country",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A supported BCP 47 tag for the gift copy; untranslated gifts keep the default copy",
          "in" : "query",
          "name" : "locale",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Plain-text search over the gift copy",
          "in" : "query",
          "name" : "q",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A category or subcategory code from GET /catalog/categories; repeat it to match any of several",
          "in" : "query",
          "name" : "category",
          "required" : false,
          "schema" : {
            "items" : {
              "type" : "string"
            },
            "type" : "array"
          }
        }, {
          "description" : "true narrows to gifts that ship as they are",
          "in" : "query",
          "name" : "readyToSend",
          "required" : false,
          "schema" : {
            "type" : "boolean"
          }
        }, {
          "description" : "ISO-8601 instant, inclusive; switches the read to catalog sync. Encode a + offset as %2B, or send Z",
          "in" : "query",
          "name" : "updatedSince",
          "required" : false,
          "schema" : {
            "format" : "date-time",
            "type" : "string"
          }
        }, {
          "description" : "The nextCursor of the previous page",
          "in" : "query",
          "name" : "after",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Page size, 1 to 100; 25 when absent",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "default" : 25,
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProductPageResponse"
                }
              }
            },
            "description" : "A page of gifts"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: country missing, malformed or not a known country; locale malformed or not a supported locale; a category code that names no category or subcategory; or an unreadable updatedSince, limit or cursor. errors[].field names it"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold CATALOG"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List gifts",
        "tags" : [ "Catalog" ]
      }
    },
    "/catalog/products/{productId}" : {
      "get" : {
        "description" : "One gift, priced and checked for the delivery country. A gift that is a draft, archived, internal or unknown answers the same 404 not_found. A listed gift that cannot be supplied to the country answers 200 with available: false.",
        "operationId" : "getProduct",
        "parameters" : [ {
          "in" : "path",
          "name" : "productId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Delivery country, ISO 3166-1 alpha-2",
          "example" : "DE",
          "in" : "query",
          "name" : "country",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A supported BCP 47 tag for the gift copy",
          "in" : "query",
          "name" : "locale",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerProduct"
                }
              }
            },
            "description" : "The gift"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: country missing, malformed or not a known country, or locale malformed or not a supported locale. errors[].field names it"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold CATALOG"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no listed gift with this id"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Read a gift",
        "tags" : [ "Catalog" ]
      }
    },
    "/events" : {
      "get" : {
        "description" : "The tenant's order and personal-link events, in commit order: an order placed, its status changed, its delivery details or shipment updated, a message posted on it, and a personal link created, approved, claimed or cancelled. Each item is the same Event a webhook delivers, so the feed replays anything a webhook missed, and it also holds the changes this key made itself, which are never sent to it as webhooks. Pass the previous page's `nextCursor` as `after` to resume: a reader resuming from any cursor sees every later event, including ones whose transaction committed late. `nextCursor` is returned on every page, the last one included, so a reader that has caught up keeps polling from it; it is null only when the feed is empty and no `after` was given. The key's scopes and brands filter the feed: order events need `ORDERS`, personal-link events need `PERSONAL_LINKS`. An `order.message_posted` event for a message this key wrote is left out, and `ping` events never appear. Events are retained 30 days. Error code: `invalid_request` (400) for a bad `limit` or `after`.",
        "operationId" : "listEvents",
        "parameters" : [ {
          "description" : "The `nextCursor` of the previous page",
          "in" : "query",
          "name" : "after",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Page size, 1 to 100; 25 by default",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "default" : 25,
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "items" : [ {
                    "data" : {
                      "order" : {
                        "id" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                        "status" : "SENT"
                      },
                      "previousStatus" : "PROCESSING"
                    },
                    "environment" : "production",
                    "id" : "0b7e5f3c-2a1d-4c6e-9f8a-7b6c5d4e3f21",
                    "occurredAt" : "2026-10-05T09:12:44Z",
                    "type" : "order.status_changed"
                  } ],
                  "nextCursor" : "eyJ0cmFuc2FjdGlvbklkIjo3NDIsInNlcXVlbmNlIjoxOX0"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/EventListResponse"
                }
              }
            },
            "description" : "A page of events"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`invalid_request`: `limit` is outside 1 to 100, or `after` is not a cursor"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "Missing, malformed, unknown or revoked key (`invalid_api_key`)"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List events",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "/me" : {
      "get" : {
        "description" : "The calling key, its tenant and the environment. `brandIds` is null when the key reaches every brand of the tenant, including ones added later. `environment` is `production` or `sandbox`. `tenant` also carries how the tenant is set up, as the writes check it: `locales` a personal link accepts, `currency`, `approvalRequired`, and `customFields` with the ids orders and personal links answer. `key.webhookUrl` is null when unset; the webhook secret is never returned.",
        "operationId" : "getMe",
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "environment" : "sandbox",
                  "key" : {
                    "brandIds" : null,
                    "id" : 42,
                    "name" : "VIP shop",
                    "prefix" : "lxr_sbx_7Hk2",
                    "scopes" : [ "CATALOG", "ORDERS" ],
                    "webhookUrl" : "https://hooks.operator.example/luxorr"
                  },
                  "tenant" : {
                    "approvalRequired" : false,
                    "currency" : "EUR",
                    "customFields" : [ {
                      "id" : "3d2c1b0a-9f8e-4d7c-8b6a-5f4e3d2c1b0a",
                      "label" : "VIP tier",
                      "options" : [ "Gold", "Platinum" ],
                      "required" : true,
                      "type" : "DROPDOWN"
                    } ],
                    "id" : "6f1c2a0e-1d2b-4c3d-8e9f-0a1b2c3d4e5f",
                    "locales" : [ "en-US", "de-DE" ],
                    "name" : "Example Operator"
                  }
                },
                "schema" : {
                  "$ref" : "#/components/schemas/MeResponse"
                }
              }
            },
            "description" : "The key"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "Missing, malformed, unknown or revoked key (`invalid_api_key`)"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Read the key",
        "tags" : [ "Keys" ]
      }
    },
    "/orders" : {
      "get" : {
        "description" : "Every order of the tenant within the key's brands, whatever placed it, newest placed first, also with `updatedSince`. Filter by `externalOrderId`, `externalRecipientId`, `status`, `brandId` and `updatedSince` (inclusive); page with `after` and `limit` (1 to 100, default 25). To sync, page to the end and pass the newest `updatedAt` you saw, less a few minutes, next time. Error code: `invalid_request` (400) for a malformed filter.",
        "operationId" : "listOrders",
        "parameters" : [ {
          "description" : "Only the order with this ID of yours",
          "in" : "query",
          "name" : "externalOrderId",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Only orders for this player of yours",
          "in" : "query",
          "name" : "externalRecipientId",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Only orders in this status",
          "in" : "query",
          "name" : "status",
          "required" : false,
          "schema" : {
            "enum" : [ "REQUESTED", "PROCESSING", "SENT", "COMPLETED", "CANCELLED" ],
            "type" : "string"
          }
        }, {
          "description" : "Only this brand's orders",
          "in" : "query",
          "name" : "brandId",
          "required" : false,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "Only orders changed at or after this instant. The list stays newest placed first, so page to the end and keep the newest updatedAt seen. Encode a + offset as %2B, or send Z",
          "in" : "query",
          "name" : "updatedSince",
          "required" : false,
          "schema" : {
            "format" : "date-time",
            "type" : "string"
          }
        }, {
          "description" : "The nextCursor of the previous page",
          "in" : "query",
          "name" : "after",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Page size, 1 to 100; 25 when absent",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "default" : 25,
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "items" : [ {
                    "brandId" : "0a6f2e1c-3b5d-4e7f-8a9b-0c1d2e3f4a5b",
                    "campaignId" : null,
                    "cancellationReason" : null,
                    "createdAt" : "2026-10-05T09:12:44Z",
                    "deliveryCountry" : "DE",
                    "externalActionRef" : "deposit-milestone-5",
                    "externalCampaignRef" : "vip-october",
                    "externalOrderId" : "ORD-1001",
                    "externalRecipientId" : "player-77",
                    "id" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                    "items" : [ {
                      "kind" : "CATALOG",
                      "productId" : "9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
                      "productName" : "Cashmere scarf",
                      "variations" : {
                        "Colour" : "Black"
                      }
                    } ],
                    "personalLinkId" : null,
                    "receivedOutsideActiveHours" : false,
                    "reference" : "G-2026004711",
                    "shipments" : [ ],
                    "source" : "API",
                    "status" : "PROCESSING",
                    "updatedAt" : "2026-10-05T09:12:44Z",
                    "urgent" : false,
                    "version" : 3
                  } ],
                  "nextCursor" : "eyJwbGFjZWRBdCI6..."
                },
                "schema" : {
                  "$ref" : "#/components/schemas/OrderListResponse"
                }
              }
            },
            "description" : "One page of orders"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "A malformed filter, limit or cursor (`invalid_request`)"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List orders",
        "tags" : [ "Orders" ]
      },
      "post" : {
        "description" : "Places one order with the partner's own ids. `items` holds exactly one item: either `{productId, variations}` or `{customProductName, budget}`. Without `campaignId` the order needs `brandId`; with one, `brandId` may be left out and, when sent, must be the campaign's brand. The order follows the tenant's approval setting, so it starts as `REQUESTED` (waiting for approval) or `PROCESSING`. `managerEmail` names a team member who then owns the order. Requires an `Idempotency-Key` header: a retry with the same key and body returns the first response and never places a second order. Error codes: `invalid_request` (400, `errors` names each field), `campaign_not_found`, `campaign_not_active`, `product_not_in_campaign`, `brand_required`, `brand_not_found`, `brand_campaign_mismatch`, `product_not_available`, `not_deliverable_to_country`, `invalid_variations`, `invalid_custom_fields`, `manager_not_found` (422), `out_of_stock` (409), `external_order_id_conflict` (409, with `orderId` when that order is within the key's brands), `idempotency_key_required` and `idempotency_key_invalid` (400), `idempotency_key_reused` (422), `unsupported_media_type` (415) for a body that is not JSON.",
        "operationId" : "createOrder",
        "parameters" : [ {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "example" : {
                "brandId" : "0a6f2e1c-3b5d-4e7f-8a9b-0c1d2e3f4a5b",
                "client" : {
                  "email" : "vip-desk@operator.example",
                  "name" : "VIP desk"
                },
                "courierComment" : "Ring twice",
                "externalOrderId" : "ORD-1001",
                "externalRecipientId" : "player-77",
                "items" : [ {
                  "productId" : "9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
                  "variations" : {
                    "Colour" : "Black"
                  }
                } ],
                "recipient" : {
                  "address" : {
                    "city" : "Berlin",
                    "country" : "DE",
                    "postalCode" : "10117",
                    "street" : "Unter den Linden 1"
                  },
                  "email" : "wendy@example.com",
                  "name" : "Wendy Player",
                  "phone" : "+4930123456"
                },
                "urgent" : false
              },
              "schema" : {
                "$ref" : "#/components/schemas/CreateOrderRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "brandId" : "0a6f2e1c-3b5d-4e7f-8a9b-0c1d2e3f4a5b",
                  "campaignId" : null,
                  "cancellationReason" : null,
                  "createdAt" : "2026-10-05T09:12:44.512731Z",
                  "deliveryCountry" : "DE",
                  "externalActionRef" : null,
                  "externalCampaignRef" : null,
                  "externalOrderId" : "ORD-1001",
                  "externalRecipientId" : "player-77",
                  "id" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                  "items" : [ {
                    "kind" : "CATALOG",
                    "productId" : "9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
                    "productName" : "Cashmere scarf",
                    "variations" : {
                      "Colour" : "Black"
                    }
                  } ],
                  "personalLinkId" : null,
                  "receivedOutsideActiveHours" : false,
                  "reference" : "G-2026004711",
                  "shipments" : [ ],
                  "source" : "API",
                  "status" : "PROCESSING",
                  "updatedAt" : "2026-10-05T09:12:44.512731Z",
                  "urgent" : false,
                  "version" : 0
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerOrderRepresentation"
                }
              }
            },
            "description" : "The order was placed, at version 0"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "example" : {
                  "code" : "invalid_request",
                  "detail" : "recipient.phone is required",
                  "errors" : [ {
                    "code" : "required",
                    "field" : "recipient.phone",
                    "message" : "recipient.phone is required"
                  } ],
                  "status" : 400,
                  "title" : "Invalid request",
                  "type" : "https://docs.luxorr.io/errors#invalid_request"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "A field is missing or invalid (`invalid_request`), or the Idempotency-Key is missing"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "example" : {
                  "code" : "external_order_id_conflict",
                  "detail" : "An order with this externalOrderId already exists: see orderId",
                  "orderId" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                  "status" : 409,
                  "title" : "External order id already used",
                  "type" : "https://docs.luxorr.io/errors#external_order_id_conflict"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`external_order_id_conflict` or `out_of_stock`"
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "The order was refused; `code` says why"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Place an order",
        "tags" : [ "Orders" ]
      }
    },
    "/orders/{orderId}" : {
      "get" : {
        "description" : "An order outside the key's tenant or brands answers `not_found`, like an unknown id. The order carries the delivery country only, never contact details or a street.",
        "operationId" : "getOrder",
        "parameters" : [ {
          "in" : "path",
          "name" : "orderId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "brandId" : "0a6f2e1c-3b5d-4e7f-8a9b-0c1d2e3f4a5b",
                  "campaignId" : null,
                  "cancellationReason" : null,
                  "createdAt" : "2026-10-05T09:12:44Z",
                  "deliveryCountry" : "DE",
                  "externalActionRef" : "deposit-milestone-5",
                  "externalCampaignRef" : "vip-october",
                  "externalOrderId" : "ORD-1001",
                  "externalRecipientId" : "player-77",
                  "id" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                  "items" : [ {
                    "kind" : "CATALOG",
                    "productId" : "9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
                    "productName" : "Cashmere scarf",
                    "variations" : {
                      "Colour" : "Black"
                    }
                  } ],
                  "personalLinkId" : null,
                  "receivedOutsideActiveHours" : false,
                  "reference" : "G-2026004711",
                  "shipments" : [ ],
                  "source" : "API",
                  "status" : "PROCESSING",
                  "updatedAt" : "2026-10-05T09:12:44Z",
                  "urgent" : false,
                  "version" : 3
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerOrderRepresentation"
                }
              }
            },
            "description" : "The order"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`not_found`"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Read an order",
        "tags" : [ "Orders" ]
      }
    },
    "/orders/{orderId}/messages" : {
      "get" : {
        "description" : "The order's conversation with Luxorr and the tenant's team, oldest first, as a plain array that is not paged. `author.kind` is `API_KEY`, `TENANT_ACCOUNT`, `TENANT_CLIENT`, `BACKOFFICE_ACCOUNT` (shown as \"Luxorr\") or `SYSTEM`. Luxorr's internal notes are never included. Error code: `not_found` (404).",
        "operationId" : "listOrderMessages",
        "parameters" : [ {
          "in" : "path",
          "name" : "orderId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : [ {
                  "author" : {
                    "kind" : "API_KEY",
                    "name" : "VIP shop"
                  },
                  "body" : "Could you confirm the delivery date?",
                  "createdAt" : "2026-10-05T09:12:44Z",
                  "id" : "6d1e2f3a-4b5c-4d6e-8f9a-0b1c2d3e4f5a"
                }, {
                  "author" : {
                    "kind" : "BACKOFFICE_ACCOUNT",
                    "name" : "Luxorr"
                  },
                  "body" : "Your gift ships on Monday",
                  "createdAt" : "2026-10-05T10:02:10Z",
                  "id" : "7e2f3a4b-5c6d-4e7f-9a0b-1c2d3e4f5a6b"
                } ],
                "schema" : {
                  "items" : {
                    "$ref" : "#/components/schemas/PartnerOrderMessageRepresentation"
                  },
                  "type" : "array"
                }
              }
            },
            "description" : "The messages"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`not_found`"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List order messages",
        "tags" : [ "Order messages" ]
      },
      "post" : {
        "description" : "Posts `{body}` (at most 4000 characters) to the order's conversation, written by this key. Luxorr and the tenant's team see it under the key's name. Requires an `Idempotency-Key` header, like every POST. Error codes: `invalid_request` (400), `not_found` (404).",
        "operationId" : "postOrderMessage",
        "parameters" : [ {
          "in" : "path",
          "name" : "orderId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/SendMessageRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "201" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "id" : "6d1e2f3a-4b5c-4d6e-8f9a-0b1c2d3e4f5a"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/MessageSentResponse"
                }
              }
            },
            "description" : "The message was posted"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`invalid_request`: the body is missing, blank or too long"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no such record that this key may see. An id that is not a UUID answers the same"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Post an order message",
        "tags" : [ "Order messages" ]
      }
    },
    "/orders/{orderId}:cancel" : {
      "post" : {
        "description" : "Cancels an order that is `REQUESTED` or `PROCESSING`, with a reason, and returns its stock. Cancelling an order that is already `CANCELLED` answers it as it is, with no change and no event. Once it is `SENT` or later, ask Luxorr through an order message instead. Error codes: `invalid_request` (400), `not_found` (404), `not_cancellable` (409, with `currentStatus`).",
        "operationId" : "cancelOrder",
        "parameters" : [ {
          "in" : "path",
          "name" : "orderId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CancelOrderRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "brandId" : "0a6f2e1c-3b5d-4e7f-8a9b-0c1d2e3f4a5b",
                  "campaignId" : null,
                  "cancellationReason" : null,
                  "createdAt" : "2026-10-05T09:12:44Z",
                  "deliveryCountry" : "DE",
                  "externalActionRef" : "deposit-milestone-5",
                  "externalCampaignRef" : "vip-october",
                  "externalOrderId" : "ORD-1001",
                  "externalRecipientId" : "player-77",
                  "id" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                  "items" : [ {
                    "kind" : "CATALOG",
                    "productId" : "9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
                    "productName" : "Cashmere scarf",
                    "variations" : {
                      "Colour" : "Black"
                    }
                  } ],
                  "personalLinkId" : null,
                  "receivedOutsideActiveHours" : false,
                  "reference" : "G-2026004711",
                  "shipments" : [ ],
                  "source" : "API",
                  "status" : "PROCESSING",
                  "updatedAt" : "2026-10-05T09:12:44Z",
                  "urgent" : false,
                  "version" : 3
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerOrderRepresentation"
                }
              }
            },
            "description" : "The cancelled order, also when it was already cancelled"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: a parameter or a body field is missing or malformed; errors[].field names it. idempotency_key_required or idempotency_key_invalid: the Idempotency-Key header is missing, blank or longer than 255 characters"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no such record that this key may see. An id that is not a UUID answers the same"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "example" : {
                  "code" : "not_cancellable",
                  "currentStatus" : "SENT",
                  "detail" : "The order is SENT and can no longer be cancelled. Post an order message ...",
                  "status" : 409,
                  "title" : "Not cancellable",
                  "type" : "https://docs.luxorr.io/errors#not_cancellable"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`not_cancellable`"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Cancel an order",
        "tags" : [ "Orders" ]
      }
    },
    "/orders/{orderId}:update-delivery" : {
      "post" : {
        "description" : "Changes the recipient's contact and address, the courier comment or urgency while the order is `PROCESSING`. `recipient`, `courierComment` and `urgent` left out keep their value. `recipient` and `recipient.address` are merged with the stored ones: each field sent replaces its stored value, and one left out or null keeps it, so a single detail can be corrected alone, also on an order placed by a personal-link claim. A field cannot be cleared: an empty `email` or `postalCode` keeps the stored one, and any other empty field answers `required`. The merged recipient is checked as a whole, as on create, and a failure answers `invalid_request` naming the `recipient.*` field, a stored value included. `expectedVersion` is the order's `version`. A request that changes nothing, such as one with only `expectedVersion`, answers the current order and keeps its `version`; it is still refused when the version is stale or the order is not `PROCESSING`. The delivery country cannot change. Error codes: `invalid_request` (400), `not_found` (404), `not_editable` (409, with `currentStatus`), `version_conflict` (409), `country_change_not_allowed` (422), `invalid_custom_fields` (422).",
        "operationId" : "updateOrderDelivery",
        "parameters" : [ {
          "in" : "path",
          "name" : "orderId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/UpdateDeliveryRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "brandId" : "0a6f2e1c-3b5d-4e7f-8a9b-0c1d2e3f4a5b",
                  "campaignId" : null,
                  "cancellationReason" : null,
                  "createdAt" : "2026-10-05T09:12:44Z",
                  "deliveryCountry" : "DE",
                  "externalActionRef" : "deposit-milestone-5",
                  "externalCampaignRef" : "vip-october",
                  "externalOrderId" : "ORD-1001",
                  "externalRecipientId" : "player-77",
                  "id" : "4c1f9a52-8d0e-4f4b-9a3e-1f2d3c4b5a69",
                  "items" : [ {
                    "kind" : "CATALOG",
                    "productId" : "9b8a7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d",
                    "productName" : "Cashmere scarf",
                    "variations" : {
                      "Colour" : "Black"
                    }
                  } ],
                  "personalLinkId" : null,
                  "receivedOutsideActiveHours" : false,
                  "reference" : "G-2026004711",
                  "shipments" : [ ],
                  "source" : "API",
                  "status" : "PROCESSING",
                  "updatedAt" : "2026-10-05T09:12:44Z",
                  "urgent" : false,
                  "version" : 3
                },
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerOrderRepresentation"
                }
              }
            },
            "description" : "The order after the change"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "example" : {
                  "code" : "invalid_request",
                  "detail" : "recipient.address.postalCode is required for DE",
                  "errors" : [ {
                    "code" : "required",
                    "field" : "recipient.address.postalCode",
                    "message" : "recipient.address.postalCode is required for DE"
                  } ],
                  "status" : 400,
                  "title" : "Invalid request",
                  "type" : "https://docs.luxorr.io/errors#invalid_request"
                },
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "A field is missing or invalid (`invalid_request`), a field of the merged recipient included"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked, or API access is switched off for the tenant"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold ORDERS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no such record that this key may see. An id that is not a UUID answers the same"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`not_editable` or `version_conflict`"
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "`country_change_not_allowed`"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Update delivery details",
        "tags" : [ "Orders" ]
      }
    },
    "/personal-links" : {
      "get" : {
        "description" : "Links within the key's brands, newest created first. With updatedSince, only links changed at or after then, oldest change first (updatedAt, then id). For the next sync, pass the newest updatedAt you hold, less a few minutes: a change committed while a sync ran can carry an earlier time. The event feed is the complete record of changes.",
        "operationId" : "listPersonalLinks",
        "parameters" : [ {
          "description" : "Only links sent to this recipient of yours",
          "in" : "query",
          "name" : "externalRecipientId",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Only this campaign's links",
          "in" : "query",
          "name" : "campaignId",
          "required" : false,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "Only links in this status",
          "in" : "query",
          "name" : "status",
          "required" : false,
          "schema" : {
            "enum" : [ "REQUESTED", "ACTIVE", "CLAIMED", "EXPIRED", "CANCELLED" ],
            "type" : "string"
          }
        }, {
          "description" : "Only links changed at or after this instant; pages oldest change first. Encode a + offset as %2B, or send Z",
          "in" : "query",
          "name" : "updatedSince",
          "required" : false,
          "schema" : {
            "format" : "date-time",
            "type" : "string"
          }
        }, {
          "description" : "The nextCursor of the previous page",
          "in" : "query",
          "name" : "after",
          "required" : false,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "Page size, 1 to 100; 25 when absent",
          "in" : "query",
          "name" : "limit",
          "required" : false,
          "schema" : {
            "default" : 25,
            "maximum" : 100,
            "minimum" : 1,
            "type" : "integer"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PersonalLinkPageResponse"
                }
              }
            },
            "description" : "A page of personal links"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: an unreadable campaignId, status, updatedSince, limit or cursor; errors[].field names it"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold PERSONAL_LINKS"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "List personal links",
        "tags" : [ "Personal links" ]
      }
    },
    "/personal-links/{linkId}" : {
      "get" : {
        "description" : "orderId is set once the recipient has claimed the link. A link of another tenant, outside the key's brands or unknown answers the same 404 not_found.",
        "operationId" : "getPersonalLink",
        "parameters" : [ {
          "in" : "path",
          "name" : "linkId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerPersonalLinkRepresentation"
                }
              }
            },
            "description" : "The personal link"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold PERSONAL_LINKS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no personal link with this id that the key can see"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Read a personal link",
        "tags" : [ "Personal links" ]
      }
    },
    "/personal-links/{linkId}:cancel" : {
      "post" : {
        "description" : "Only a REQUESTED or ACTIVE link can be cancelled. The recipient sees the link as expired; the reason is kept for the tenant and never shown to them. Cancelling a link that is already CANCELLED answers it as it is, with no change and no event.",
        "operationId" : "cancelPersonalLink",
        "parameters" : [ {
          "in" : "path",
          "name" : "linkId",
          "required" : true,
          "schema" : {
            "type" : "string"
          }
        }, {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CancelRequest"
              }
            }
          }
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/PartnerPersonalLinkRepresentation"
                }
              }
            },
            "description" : "The cancelled personal link, also when it was already cancelled"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: reason is missing, blank or longer than 1,000 characters"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold PERSONAL_LINKS"
          },
          "404" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_found: no personal link with this id that the key can see"
          },
          "409" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "not_cancellable: the link is CLAIMED or EXPIRED; currentStatus says which"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Cancel a personal link",
        "tags" : [ "Personal links" ]
      }
    },
    "/personal-links:create-batch" : {
      "post" : {
        "description" : "Each recipient is validated on its own: the valid ones are created in one transaction and the invalid ones are reported by index with the reason, so resending only the rejected recipients completes the batch. Links start REQUESTED when the tenant requires approval, otherwise ACTIVE. Each link created records a personal_link.created event, which the feed shows this key but no webhook sends it.",
        "operationId" : "createPersonalLinkBatch",
        "parameters" : [ {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "$ref" : "#/components/schemas/CreateBatchRequest"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/CreateBatchResponse"
                }
              }
            },
            "description" : "One result per recipient, in request order"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: neither campaignId nor brandId, both, brandId without productIds, or an unreadable id; errors[].field names it. idempotency_key_required: no Idempotency-Key"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_api_key: the key is missing, malformed, unknown or revoked"
          },
          "403" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "insufficient_scope: the key does not hold PERSONAL_LINKS"
          },
          "422" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "Nothing was created. campaign_not_found, campaign_not_active, brand_not_found, no_products, product_not_found, product_not_available, no_recipients, too_many_recipients (more than 1,000), or idempotency_key_reused"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Create personal links",
        "tags" : [ "Personal links" ]
      }
    },
    "/webhooks:test" : {
      "post" : {
        "description" : "Sends a signed `ping` event to the key's webhook URL now. Delivers synchronously and reports the receiver's HTTP status in `responseStatus`. A 2xx answer comes back as `{\"responseStatus\": 200, \"error\": null}`. Any other answer sets both: `responseStatus` and an `error` such as \"The receiver answered HTTP 500\". When the receiver cannot be reached, `responseStatus` is null and `error` says why. A key with no webhook URL also answers 200, with `responseStatus` null and `error` \"This key has no webhook URL\". Requires an `Idempotency-Key` header, like every POST.",
        "operationId" : "sendTestWebhook",
        "parameters" : [ {
          "description" : "A new unique value, such as a fresh UUID, for each new request, and the same value for every retry of it. A retry with the same key and request replays the first answer with `Idempotent-Replayed: true`; the same key with a different request answers 422 `idempotency_key_reused`; a retry while the first is still running answers 409 `idempotency_request_in_progress`; a key longer than 255 characters answers 400 `idempotency_key_invalid`. Kept 7 days.",
          "in" : "header",
          "name" : "Idempotency-Key",
          "required" : true,
          "schema" : {
            "maxLength" : 255,
            "type" : "string"
          }
        } ],
        "responses" : {
          "200" : {
            "content" : {
              "application/json" : {
                "example" : {
                  "error" : null,
                  "responseStatus" : 200
                },
                "schema" : {
                  "$ref" : "#/components/schemas/TestEventResponse"
                }
              }
            },
            "description" : "The receiver's answer, or why there was none"
          },
          "400" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "invalid_request: a parameter or a body field is missing or malformed; errors[].field names it. idempotency_key_required or idempotency_key_invalid: the Idempotency-Key header is missing, blank or longer than 255 characters"
          },
          "401" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "Missing, malformed, unknown or revoked key (`invalid_api_key`)"
          },
          "429" : {
            "content" : {
              "application/problem+json" : {
                "schema" : {
                  "$ref" : "#/components/schemas/ProblemDetail"
                }
              }
            },
            "description" : "rate_limited: more than 300 requests a minute from this key; see Retry-After"
          }
        },
        "summary" : "Send a test event",
        "tags" : [ "Events and webhooks" ]
      }
    }
  },
  "security" : [ {
    "apiKey" : [ ]
  } ],
  "servers" : [ {
    "description" : "Production",
    "url" : "https://api.luxorr.io/api/public/v1"
  }, {
    "description" : "Sandbox",
    "url" : "https://api.sandbox.luxorr.io/api/public/v1"
  } ],
  "tags" : [ {
    "description" : "The calling key, its tenant and the environment that answered.",
    "name" : "Keys"
  }, {
    "description" : "Brands, the gift taxonomy, gifts for a delivery country, catalog sync and key-less images. Needs CATALOG, except brands and images.",
    "name" : "Catalog"
  }, {
    "description" : "The campaigns Luxorr prepared for the tenant, with stock. Needs CATALOG.",
    "name" : "Campaigns"
  }, {
    "description" : "Place orders with your own IDs, find, read, correct and cancel them. Needs ORDERS.",
    "name" : "Orders"
  }, {
    "description" : "An order's conversation with Luxorr and the tenant's team. Needs ORDERS.",
    "name" : "Order messages"
  }, {
    "description" : "Send gift links in batches, read and withdraw them. Needs PERSONAL_LINKS.",
    "name" : "Personal links"
  }, {
    "description" : "The replayable event feed, the webhook test and the signed webhooks Luxorr sends. Any scope.",
    "name" : "Events and webhooks"
  } ],
  "webhooks" : {
    "order.created" : {
      "post" : {
        "description" : "`data` is the Order, as `GET /orders/{orderId}` returns it. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_order_created",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is the Order, as `GET /orders/{orderId}` returns it.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "order.created" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: order.created",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "order.message_posted" : {
      "post" : {
        "description" : "`data` is `{orderId, externalOrderId, message}`, where `message` is shaped like an item of `GET /orders/{orderId}/messages`. A message the receiving key wrote is never sent back to it. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_order_message_posted",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is `{orderId, externalOrderId, message}`, where `message` is shaped like an item of `GET /orders/{orderId}/messages`. A message the receiving key wrote is never sent back to it.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "order.message_posted" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: order.message_posted",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "order.status_changed" : {
      "post" : {
        "description" : "`data` is `{order, previousStatus}`: the Order after the change and the status it moved from. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_order_status_changed",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is `{order, previousStatus}`: the Order after the change and the status it moved from.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "order.status_changed" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: order.status_changed",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "order.updated" : {
      "post" : {
        "description" : "`data` is the Order after its delivery details or shipment changed. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_order_updated",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is the Order after its delivery details or shipment changed.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "order.updated" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: order.updated",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "personal_link.approved" : {
      "post" : {
        "description" : "`data` is the PersonalLink, now `ACTIVE`. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_personal_link_approved",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is the PersonalLink, now `ACTIVE`.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "personal_link.approved" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: personal_link.approved",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "personal_link.cancelled" : {
      "post" : {
        "description" : "`data` is the PersonalLink, now `CANCELLED`. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_personal_link_cancelled",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is the PersonalLink, now `CANCELLED`.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "personal_link.cancelled" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: personal_link.cancelled",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "personal_link.claimed" : {
      "post" : {
        "description" : "`data` is the PersonalLink, with `orderId` set to the order the claim placed. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_personal_link_claimed",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is the PersonalLink, with `orderId` set to the order the claim placed.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "personal_link.claimed" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: personal_link.claimed",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "personal_link.created" : {
      "post" : {
        "description" : "`data` is the PersonalLink as created: `REQUESTED` when the tenant requires approval, otherwise `ACTIVE`. One event per link, whoever created it; the key that created the links is not sent them. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_personal_link_created",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is the PersonalLink as created: `REQUESTED` when the tenant requires approval, otherwise `ACTIVE`. One event per link, whoever created it; the key that created the links is not sent them.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "personal_link.created" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: personal_link.created",
        "tags" : [ "Events and webhooks" ]
      }
    },
    "ping" : {
      "post" : {
        "description" : "`data` is `{}`. Sent only by `POST /webhooks:test`, to the key that asked. Delivered as a POST to the key's webhook URL, at least once and not strictly in order: deduplicate by `id`, treat the resource's `updatedAt` as the truth, and read `GET /events` to reconcile. Any 2xx answer counts as delivered; anything else is retried with exponential backoff for 8 attempts over about 24 hours. A change made by a key's own request is never sent to that key; `GET /events` holds it, unless it is the key's own order message.",
        "operationId" : "webhook_ping",
        "parameters" : [ {
          "description" : "The event's `id`, the same as in the body",
          "in" : "header",
          "name" : "Luxorr-Event-Id",
          "required" : true,
          "schema" : {
            "format" : "uuid",
            "type" : "string"
          }
        }, {
          "description" : "`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the key's webhook secret>`",
          "in" : "header",
          "name" : "Luxorr-Signature",
          "required" : true,
          "schema" : {
            "example" : "t=1759655564,v1=5f2b…",
            "type" : "string"
          }
        } ],
        "requestBody" : {
          "content" : {
            "application/json" : {
              "schema" : {
                "properties" : {
                  "data" : {
                    "description" : "`data` is `{}`. Sent only by `POST /webhooks:test`, to the key that asked.",
                    "type" : "object"
                  },
                  "environment" : {
                    "enum" : [ "production", "sandbox" ],
                    "type" : "string"
                  },
                  "id" : {
                    "format" : "uuid",
                    "type" : "string"
                  },
                  "occurredAt" : {
                    "format" : "date-time",
                    "type" : "string"
                  },
                  "type" : {
                    "enum" : [ "ping" ],
                    "type" : "string"
                  }
                },
                "required" : [ "data", "environment", "id", "occurredAt", "type" ],
                "type" : "object"
              }
            }
          },
          "required" : true
        },
        "responses" : {
          "2XX" : {
            "description" : "The event was received"
          }
        },
        "summary" : "Webhook: ping",
        "tags" : [ "Events and webhooks" ]
      }
    }
  }
}
