import {z} from 'zod' export type LoyaltyV2ActivityEarningRuleError = {message: string}; export type LoyaltyV2ActivityMetadata = {[key: string]: unknown}; export type LoyaltyV2ActivityEarningRuleTriggerCustomEvent = {schema_id: string}; export type LoyaltyV2ActivityEarningRuleTriggerSegment = {id: string}; export type EarningRuleTrigger = {event: 'customer.order.paid' | 'customer.custom_event' | 'customer.segment.entered', custom_event?: (LoyaltyV2ActivityEarningRuleTriggerCustomEvent | null) | undefined, segment?: (LoyaltyV2ActivityEarningRuleTriggerSegment | null) | undefined}; export type EarningRuleRulesGroup = {logic: string}; export type LoyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationPeriod = {unit: 'DAY' | 'MONTH' | 'YEAR', value: number}; export type LoyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationRounding = {type: 'END_OF_MONTH' | 'END_OF_QUARTER' | 'END_OF_HALF_YEAR' | 'END_OF_YEAR' | 'END_OF_PARTICULAR_MONTH', value?: (number | null) | undefined}; export type EarningRuleEffectPointsExpirationRollingExpiration = {period: LoyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationPeriod, rounding?: (LoyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationRounding | null) | undefined}; export type LoyaltyV2ActivityEarningRuleEffectPointsExpirationCalendarExpirationDate = {day: number, month: number}; export type EarningRuleEffectPointsExpirationCalendarExpiration = {expiration_dates: Array}; export type LoyaltyV2ActivityEarningRuleEffectPointsExpirationSlidingExpirationPeriod = {value: number, unit: 'DAY' | 'MONTH' | 'YEAR'}; export type EarningRuleEffectPointsExpirationSlidingExpiration = {earning_activity: boolean, period: LoyaltyV2ActivityEarningRuleEffectPointsExpirationSlidingExpirationPeriod}; export type EarningRuleEffectPointsExpiration = {type: 'NO_EXPIRATION' | 'ROLLING_EXPIRATION' | 'CALENDAR_EXPIRATION' | 'SLIDING_EXPIRATION', rolling_expiration?: (EarningRuleEffectPointsExpirationRollingExpiration | null) | undefined, calendar_expiration?: (EarningRuleEffectPointsExpirationCalendarExpiration | null) | undefined, sliding_expiration?: (EarningRuleEffectPointsExpirationSlidingExpiration | null) | undefined}; export type EarningRuleEffectPoints = {value: number, card_definition_id: string, points_expiration?: (EarningRuleEffectPointsExpiration | null) | undefined}; export type LoyaltyV2ActivityEarningRulePointsProportionalEvery = {every: number, value: number}; export type LoyaltyV2ActivityEarningRulePointsProportionalMetadata = {every: number, value: number, property: string}; export type EarningRulePointsProportionalOrder = {amount?: LoyaltyV2ActivityEarningRulePointsProportionalEvery | undefined, total_amount?: LoyaltyV2ActivityEarningRulePointsProportionalEvery | undefined, metadata?: LoyaltyV2ActivityEarningRulePointsProportionalMetadata | undefined}; export type EarningRulePointsProportionalCustomer = {metadata: LoyaltyV2ActivityEarningRulePointsProportionalMetadata}; export type EarningRulePointsProportionalCustomEvent = {metadata: LoyaltyV2ActivityEarningRulePointsProportionalMetadata}; export type LoyaltyV2ActivityEarningRulePointsProportionalApplicableToProduct = {id: string}; export type LoyaltyV2ActivityEarningRulePointsProportionalApplicableToSku = {id: string}; export type LoyaltyV2ActivityEarningRulePointsProportionalApplicableToProductsCollection = {id: string}; export type EarningRulePointsProportionalApplicableTo = {type: 'product' | 'sku' | 'products_collection', product?: LoyaltyV2ActivityEarningRulePointsProportionalApplicableToProduct | undefined, sku?: LoyaltyV2ActivityEarningRulePointsProportionalApplicableToSku | undefined, products_collection?: LoyaltyV2ActivityEarningRulePointsProportionalApplicableToProductsCollection | undefined}; export type EarningRulePointsProportionalOrderItemsCalculation = {every: number, value: number, applicable_to: Array}; export type EarningRulePointsProportionalOrderItems = {amount?: EarningRulePointsProportionalOrderItemsCalculation | undefined, subtotal_amount?: EarningRulePointsProportionalOrderItemsCalculation | undefined, quantity?: EarningRulePointsProportionalOrderItemsCalculation | undefined}; export type EarningRuleEffectPointsProportional = {calculation_type: 'PRE_DISCOUNT_ORDER_AMOUNT' | 'POST_DISCOUNT_ORDER_AMOUNT' | 'PRE_DISCOUNT_ORDER_ITEMS_AMOUNT' | 'POST_DISCOUNT_ORDER_ITEMS_AMOUNT' | 'ORDER_ITEMS_QUANTITY' | 'ORDER_METADATA_VALUE' | 'CUSTOMER_METADATA_VALUE' | 'CUSTOM_EVENT_METADATA_VALUE', card_definition_id: string, points_expiration?: (EarningRuleEffectPointsExpiration | null) | undefined, order?: EarningRulePointsProportionalOrder | undefined, customer?: EarningRulePointsProportionalCustomer | undefined, custom_event?: EarningRulePointsProportionalCustomEvent | undefined, order_items?: EarningRulePointsProportionalOrderItems | undefined}; export type LoyaltyV2ActivityEarningRuleEffectBenefit = {id: string}; export type EarningRuleEffect = {type: 'POINTS' | 'POINTS_PROPORTIONAL' | 'BENEFIT', points?: EarningRuleEffectPoints | undefined, points_proportional?: EarningRuleEffectPointsProportional | undefined, benefit?: LoyaltyV2ActivityEarningRuleEffectBenefit | undefined}; export type LoyaltyV2ActivityEarningRuleTierRulesAnyOfEntry = {tier_structure_id: string, tier_ids: Array}; export type EarningRuleTierRules = {type: 'NO_REQUIREMENTS' | 'ANY_OF', any_of?: (Array | null) | undefined}; export type EarningRuleEarningUpdate = {rules?: (EarningRuleRulesGroup | null) | undefined, effects: Array, name?: (string | null) | undefined, tier_rules?: (EarningRuleTierRules | null) | undefined, id?: string | undefined}; export type LoyaltyV2ActivityEarningRuleValidityDailyHours = {days_of_week: Array, start_time: string, end_time: string}; export type EarningRuleValidityHours = {type: 'DAILY' | 'ANY_TIME', daily?: (Array | null) | undefined}; export type LoyaltyV2ActivityEarningRuleTriggerLimitsCooldownFixedCooldownPeriod = {value: number, unit: 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR'}; export type EarningRuleTriggerLimitsCooldownFixedCooldown = {period: LoyaltyV2ActivityEarningRuleTriggerLimitsCooldownFixedCooldownPeriod}; export type EarningRuleTriggerLimitsCooldown = {type: 'NO_COOLDOWN' | 'FIXED_COOLDOWN', fixed_cooldown?: (EarningRuleTriggerLimitsCooldownFixedCooldown | null) | undefined}; export type LoyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedCurrentPeriod = {unit: 'DAY' | 'WEEK' | 'MONTH' | 'QUARTER' | 'YEAR'}; export type EarningRuleTriggerLimitsFrequencyLimitTimeBasedPeriod = {type: 'CURRENT_PERIOD', current_period?: (LoyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedCurrentPeriod | null) | undefined}; export type LoyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedTriggers = {max: number}; export type EarningRuleTriggerLimitsFrequencyLimit = {type: 'TIME_BASED', period: EarningRuleTriggerLimitsFrequencyLimitTimeBasedPeriod, triggers: LoyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedTriggers}; export type EarningRuleTriggerLimitsFrequency = {type: 'NO_LIMIT' | 'LIMITED', limits?: (Array | null) | undefined}; export type EarningRuleTriggerLimits = {cooldown?: (EarningRuleTriggerLimitsCooldown | null) | undefined, frequency?: (EarningRuleTriggerLimitsFrequency | null) | undefined}; export type LoyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedCurrentPeriod = {unit: 'DAY' | 'WEEK' | 'MONTH' | 'QUARTER' | 'YEAR'}; export type LoyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPeriod = {type: 'CURRENT_PERIOD', current_period?: (LoyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedCurrentPeriod | null) | undefined}; export type LoyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPoints = {max: number}; export type LoyaltyV2ActivityEarningRuleEarningLimitsGlobalLimit = {type: 'TIME_BASED', period: LoyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPeriod, points: LoyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPoints}; export type LoyaltyV2ActivityEarningRuleEarningLimitsGlobal = {type: 'NO_LIMIT' | 'LIMITED', limits?: Array | undefined}; export type LoyaltyV2ActivityEarningRuleEarningLimits = {global: LoyaltyV2ActivityEarningRuleEarningLimitsGlobal}; export type V2LoyaltiesEarningRulesUpdateRequestBody = {error?: (LoyaltyV2ActivityEarningRuleError | null) | undefined, start_date?: (string | null) | undefined, end_date?: (string | null) | undefined, metadata?: (LoyaltyV2ActivityMetadata | null) | undefined, name?: string | undefined, trigger?: EarningRuleTrigger | undefined, earnings?: Array | undefined, validity_hours?: (EarningRuleValidityHours | null) | undefined, trigger_limits?: (EarningRuleTriggerLimits | null) | undefined, earning_limits?: (LoyaltyV2ActivityEarningRuleEarningLimits | null) | undefined}; export type UpdateApiV2LoyaltiesEarningRulesEarningRuleIdArgs = {body: V2LoyaltiesEarningRulesUpdateRequestBody}; export type UpdateApiV2LoyaltiesEarningRulesEarningRuleIdOptions = {baseUrl?: string | undefined, XAppId?: string | undefined, XAppToken?: string | undefined, fetch?: typeof fetch | undefined}; export const earningRuleRulesGroup = z.object({logic: z.string()}); export const loyaltyV2ActivityEarningRuleTierRulesAnyOfEntry = z.object({tier_structure_id: z.string(), tier_ids: z.array(z.string())}); export const earningRuleTierRules = z.object({type: z.enum(["NO_REQUIREMENTS", "ANY_OF"]), any_of: z.array(loyaltyV2ActivityEarningRuleTierRulesAnyOfEntry).nullable().optional()}); export const loyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationPeriod = z.object({unit: z.enum(["DAY", "MONTH", "YEAR"]), value: z.number().int().gte(1)}); export const loyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationRounding = z.object({type: z.enum(["END_OF_MONTH", "END_OF_QUARTER", "END_OF_HALF_YEAR", "END_OF_YEAR", "END_OF_PARTICULAR_MONTH"]), value: z.number().int().gte(1).lte(12).nullable().optional()}); export const earningRuleEffectPointsExpirationRollingExpiration = z.object({period: loyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationPeriod, rounding: loyaltyV2ActivityEarningRuleEffectPointsExpirationRollingExpirationRounding.nullable().optional()}); export const loyaltyV2ActivityEarningRuleEffectPointsExpirationCalendarExpirationDate = z.object({day: z.number().int().gte(1).lte(31), month: z.number().int().gte(1).lte(12)}); export const earningRuleEffectPointsExpirationCalendarExpiration = z.object({expiration_dates: z.array(loyaltyV2ActivityEarningRuleEffectPointsExpirationCalendarExpirationDate)}); export const loyaltyV2ActivityEarningRuleEffectPointsExpirationSlidingExpirationPeriod = z.object({value: z.number().int().gte(1), unit: z.enum(["DAY", "MONTH", "YEAR"])}); export const earningRuleEffectPointsExpirationSlidingExpiration = z.object({earning_activity: z.boolean(), period: loyaltyV2ActivityEarningRuleEffectPointsExpirationSlidingExpirationPeriod}); export const earningRuleEffectPointsExpiration = z.object({type: z.enum(["NO_EXPIRATION", "ROLLING_EXPIRATION", "CALENDAR_EXPIRATION", "SLIDING_EXPIRATION"]), rolling_expiration: earningRuleEffectPointsExpirationRollingExpiration.nullable().optional(), calendar_expiration: earningRuleEffectPointsExpirationCalendarExpiration.nullable().optional(), sliding_expiration: earningRuleEffectPointsExpirationSlidingExpiration.nullable().optional()}); export const earningRuleEffectPoints = z.object({value: z.number().int().gte(0).lte(9007199254740991), card_definition_id: z.string(), points_expiration: earningRuleEffectPointsExpiration.nullable().optional()}); export const loyaltyV2ActivityEarningRulePointsProportionalEvery = z.object({every: z.number().int().gte(1).lte(9007199254740991), value: z.number().gte(0).lte(9007199254740991)}); export const loyaltyV2ActivityEarningRulePointsProportionalMetadata = z.object({every: z.number().int().gte(1).lte(9007199254740991), value: z.number().gte(0).lte(9007199254740991), property: z.string().min(1)}); export const earningRulePointsProportionalOrder = z.object({amount: loyaltyV2ActivityEarningRulePointsProportionalEvery.optional(), total_amount: loyaltyV2ActivityEarningRulePointsProportionalEvery.optional(), metadata: loyaltyV2ActivityEarningRulePointsProportionalMetadata.optional()}); export const earningRulePointsProportionalCustomer = z.object({metadata: loyaltyV2ActivityEarningRulePointsProportionalMetadata}); export const earningRulePointsProportionalCustomEvent = z.object({metadata: loyaltyV2ActivityEarningRulePointsProportionalMetadata}); export const loyaltyV2ActivityEarningRulePointsProportionalApplicableToProduct = z.object({id: z.string()}); export const loyaltyV2ActivityEarningRulePointsProportionalApplicableToSku = z.object({id: z.string()}); export const loyaltyV2ActivityEarningRulePointsProportionalApplicableToProductsCollection = z.object({id: z.string()}); export const earningRulePointsProportionalApplicableTo = z.object({type: z.enum(["product", "sku", "products_collection"]), product: loyaltyV2ActivityEarningRulePointsProportionalApplicableToProduct.optional(), sku: loyaltyV2ActivityEarningRulePointsProportionalApplicableToSku.optional(), products_collection: loyaltyV2ActivityEarningRulePointsProportionalApplicableToProductsCollection.optional()}); export const earningRulePointsProportionalOrderItemsCalculation = z.object({every: z.number().int().gte(1).lte(9007199254740991), value: z.number().gte(0).lte(9007199254740991), applicable_to: z.array(earningRulePointsProportionalApplicableTo)}); export const earningRulePointsProportionalOrderItems = z.object({amount: earningRulePointsProportionalOrderItemsCalculation.optional(), subtotal_amount: earningRulePointsProportionalOrderItemsCalculation.optional(), quantity: earningRulePointsProportionalOrderItemsCalculation.optional()}); export const earningRuleEffectPointsProportional = z.object({calculation_type: z.enum(["PRE_DISCOUNT_ORDER_AMOUNT", "POST_DISCOUNT_ORDER_AMOUNT", "PRE_DISCOUNT_ORDER_ITEMS_AMOUNT", "POST_DISCOUNT_ORDER_ITEMS_AMOUNT", "ORDER_ITEMS_QUANTITY", "ORDER_METADATA_VALUE", "CUSTOMER_METADATA_VALUE", "CUSTOM_EVENT_METADATA_VALUE"]), card_definition_id: z.string(), points_expiration: earningRuleEffectPointsExpiration.nullable().optional(), order: earningRulePointsProportionalOrder.optional(), customer: earningRulePointsProportionalCustomer.optional(), custom_event: earningRulePointsProportionalCustomEvent.optional(), order_items: earningRulePointsProportionalOrderItems.optional()}); export const loyaltyV2ActivityEarningRuleEffectBenefit = z.object({id: z.string()}); export const earningRuleEffect = z.object({type: z.enum(["POINTS", "POINTS_PROPORTIONAL", "BENEFIT"]), points: earningRuleEffectPoints.optional(), points_proportional: earningRuleEffectPointsProportional.optional(), benefit: loyaltyV2ActivityEarningRuleEffectBenefit.optional()}); export const earningRuleEarning = z.object({id: z.string(), name: z.string().max(200).nullable().optional(), rules: earningRuleRulesGroup.optional(), tier_rules: earningRuleTierRules, effects: z.array(earningRuleEffect)}); export const loyaltyV2ActivityEarningRuleTriggerCustomEvent = z.object({schema_id: z.string()}); export const loyaltyV2ActivityEarningRuleTriggerSegment = z.object({id: z.string()}); export const earningRuleTrigger = z.object({event: z.enum(["customer.order.paid", "customer.custom_event", "customer.segment.entered"]), custom_event: loyaltyV2ActivityEarningRuleTriggerCustomEvent.nullable().optional(), segment: loyaltyV2ActivityEarningRuleTriggerSegment.nullable().optional()}); export const loyaltyV2ActivityEarningRuleError = z.object({message: z.string().min(1).max(200)}); export const loyaltyV2ActivityEarningRuleValidityDailyHours = z.object({days_of_week: z.array(z.number().int().gte(0).lte(6)), start_time: z.string(), end_time: z.string()}); export const earningRuleValidityHours = z.object({type: z.enum(["DAILY", "ANY_TIME"]), daily: z.array(loyaltyV2ActivityEarningRuleValidityDailyHours).nullable().optional()}); export const loyaltyV2ActivityEarningRuleTriggerLimitsCooldownFixedCooldownPeriod = z.object({value: z.number().int().gte(1), unit: z.enum(["HOUR", "DAY", "WEEK", "MONTH", "YEAR"])}); export const earningRuleTriggerLimitsCooldownFixedCooldown = z.object({period: loyaltyV2ActivityEarningRuleTriggerLimitsCooldownFixedCooldownPeriod}); export const loyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedCurrentPeriod = z.object({unit: z.enum(["DAY", "WEEK", "MONTH", "QUARTER", "YEAR"])}); export const earningRuleTriggerLimitsFrequencyLimitTimeBasedPeriod = z.object({type: z.literal("CURRENT_PERIOD"), current_period: loyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedCurrentPeriod.nullable().optional()}); export const loyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedTriggers = z.object({max: z.number().int().gte(1)}); export const earningRuleTriggerLimitsFrequencyLimit = z.object({type: z.literal("TIME_BASED"), period: earningRuleTriggerLimitsFrequencyLimitTimeBasedPeriod, triggers: loyaltyV2ActivityEarningRuleTriggerLimitsFrequencyLimitTimeBasedTriggers}); export const loyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedCurrentPeriod = z.object({unit: z.enum(["DAY", "WEEK", "MONTH", "QUARTER", "YEAR"])}); export const loyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPeriod = z.object({type: z.literal("CURRENT_PERIOD"), current_period: loyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedCurrentPeriod.nullable().optional()}); export const loyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPoints = z.object({max: z.number().int().gte(1)}); export const loyaltyV2ActivityEarningRuleEarningLimitsGlobalLimit = z.object({type: z.literal("TIME_BASED"), period: loyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPeriod, points: loyaltyV2ActivityEarningRuleEarningLimitsGlobalTimeBasedPoints}); export const loyaltyV2ActivityEarningRuleEarningLimitsGlobal = z.object({type: z.enum(["NO_LIMIT", "LIMITED"]), limits: z.array(loyaltyV2ActivityEarningRuleEarningLimitsGlobalLimit).optional()}); export const loyaltyV2ActivityEarningRuleEarningLimits = z.object({global: loyaltyV2ActivityEarningRuleEarningLimitsGlobal}); export const loyaltyV2ActivityMetadata = z.record(z.string(), z.unknown()); export const v2LoyaltiesEarningRulesUpdateResponseBody = z.object({id: z.string(), name: z.string().max(200), status: z.enum(["DRAFT", "ACTIVE", "INACTIVE"]), earnings: z.array(earningRuleEarning), trigger: earningRuleTrigger, error: loyaltyV2ActivityEarningRuleError.optional(), validity_hours: earningRuleValidityHours, start_date: z.string().nullable(), end_date: z.string().nullable(), trigger_limits: z.object({cooldown: z.object({type: z.enum(["NO_COOLDOWN", "FIXED_COOLDOWN"]), fixed_cooldown: earningRuleTriggerLimitsCooldownFixedCooldown.nullable().optional()}).nullable(), frequency: z.object({type: z.enum(["NO_LIMIT", "LIMITED"]), limits: z.array(earningRuleTriggerLimitsFrequencyLimit).nullable().optional()}).nullable()}), earning_limits: loyaltyV2ActivityEarningRuleEarningLimits, metadata: loyaltyV2ActivityMetadata, created_at: z.string(), updated_at: z.string().nullable(), object: z.literal("earning_rule")}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Update earning rule * * PUT /v2/loyalties/earning-rules/{earningRuleId} * * Also accepts auth: bearerAuth */ export const updateApiV2LoyaltiesEarningRulesEarningRuleId = async (args: UpdateApiV2LoyaltiesEarningRulesEarningRuleIdArgs, options?: UpdateApiV2LoyaltiesEarningRulesEarningRuleIdOptions) => { const {baseUrl = "https://api.voucherify.io", fetch: fetchFn = fetch, XAppId, XAppToken} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (XAppId !== undefined) headers.set("X-App-Id", XAppId) if (XAppToken !== undefined) headers.set("X-App-Token", XAppToken) const url = `${baseUrl.replace(/\/+$/, '')}/v2/loyalties/earning-rules/${encodeURIComponent(String(args.earningRuleId))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PUT", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(v2LoyaltiesEarningRulesUpdateResponseBody, await res.json()) };