import {z} from 'zod' export type StrategyPlanDuration = {use_campaign_start?: boolean | undefined, use_campaign_end?: boolean | undefined, start_date?: (string | null) | undefined, end_date?: (string | null) | undefined}; export type StrategyPlanBudget = {budget?: (number | null) | undefined, currency_code?: string | undefined}; export type StrategyPlanGoals = {goal_type?: ('spend' | 'reach' | 'cpc' | 'cpe' | 'cpa' | 'roi' | 'ctr' | 'vcr' | 'viewability_rate' | 'vcpm' | '') | undefined, goal_value?: number | undefined, min_bid?: number | undefined, max_bid?: number | undefined, roi_target?: (number | null) | undefined, bid_min_devices?: (number | null) | undefined, bid_aggressiveness?: number | undefined, bid_price_is_media_only?: boolean | undefined, max_bid_wm?: (number | null) | undefined, use_bid_shading?: boolean | undefined}; export type StrategyPlanFrequency = {frequency_type?: ('even' | 'asap' | 'no-limit' | 't1-optimized' | null) | undefined, frequency_interval?: ('hour' | 'day' | 'week' | 'month' | 'campaign' | 'not-applicable') | undefined, frequency_amount?: number | undefined, frequency_optimization?: boolean | undefined}; export type DomainRestriction = {domain: string, target_type: 'DOMAIN' | 'APP'}; export type SiteList = {site_list_id: number, assigned: boolean}; export type Deal = {deal_id: number}; export type DealGroup = {deal_group_id: number}; export type SupplySource = {supply_source_id: number}; export type StrategyPlanInventory = {run_on_all_pmp: boolean, run_on_all_exchanges: boolean, site_restriction_transparent_urls?: boolean | undefined, domain_restrictions?: ({include?: Array | undefined, exclude?: Array | undefined}) | undefined, site_lists?: Array | undefined, deals?: Array | undefined, deal_groups?: Array | undefined, supply_sources?: Array | undefined}; export type StrategyAudienceSegment = {audience_segment_id: number, user_cpm?: (number | null) | undefined}; export type StrategyContextualSegment = {targeting_segment_id: number, user_cpm?: (number | null) | undefined}; export type TargetingPostalCodes = {restriction?: string | undefined, codes?: Array | undefined}; export type StrategyGeofence = {operator?: ('AND' | 'OR') | undefined, segments?: (Array<{geofence_segment_id?: number | undefined, geofence_segment_factual_id?: string | undefined, place_list_id?: number | undefined}>) | undefined}; export type StrategyMyData = {operator?: ('AND' | 'OR') | undefined, pixels: Array<{pixel_id: number}>}; export type StrategyLocation = {operator?: ('AND' | 'OR') | undefined, target_value_id: number, code: 'DMAX' | 'REGN' | 'CITY' | 'COUNTRY'}; export type StrategyTechnology = {operator?: ('AND' | 'OR') | undefined, code: 'BSER' | 'CSPD' | 'DVCE' | 'ISPX' | 'OSXX' | 'INVT' | 'VPSZ' | 'VLIN' | 'VCON' | 'VAUD' | 'VSKP' | 'VPLC' | 'DVMD' | 'BRLG' | 'IPTA' | 'HYPL', target_value_id: number}; export type TargetingIpAddresses = {restriction?: ('INCLUDE' | 'EXCLUDE' | '') | undefined, codes?: Array | undefined}; export type DayPart = {user_time?: boolean | undefined, start_hour: number, end_hour: number, days: Array<'M' | 'T' | 'W' | 'R' | 'F' | 'S' | 'U'>}; export type StrategyPlanTargeting = {fold_position?: (Array<'ABOVE' | 'BELOW' | 'UNCATEGORIZED'> | null) | undefined, audience?: ({include?: (Array<{operator?: ('AND' | 'OR') | undefined, segments?: Array | undefined}>) | undefined, exclude?: ({operator?: ('AND' | 'OR') | undefined, segments?: Array | undefined}) | undefined}) | undefined, contextual?: ({include?: (Array<{code?: string | undefined, operator?: ('AND' | 'OR') | undefined, segments?: Array | undefined}>) | undefined, exclude?: ({code?: string | undefined, operator?: ('AND' | 'OR') | undefined, segments: Array}) | undefined}) | undefined, postal_codes?: TargetingPostalCodes | undefined, geofence?: ({include?: StrategyGeofence | undefined, exclude?: StrategyGeofence | undefined}) | undefined, my_data?: ({include?: StrategyMyData | undefined, exclude?: StrategyMyData | undefined}) | undefined, location?: ({include?: Array | undefined, exclude?: Array | undefined}) | undefined, technology?: ({include?: Array | undefined, exclude?: Array | undefined}) | undefined, ip_addresses?: TargetingIpAddresses | undefined, day_parts?: Array | undefined, recency?: Array<{pixel_id: number, from_hour: number, to_hour: number}> | undefined, language_codes?: (Array<{code?: string | undefined, name?: string | undefined}>) | undefined}; export type StrategyPlanCreatives = {ad_expandable: boolean | null, ad_formats: Array | null, ad_sizes: Array | null}; export type CreateApiNewStrategyPlansForecastArgs = {body: {advertiser_id?: number | undefined, campaign_plan_id?: number | undefined, channels?: (Array<'display' | 'video' | 'audio' | 'ctv' | 'native'>) | undefined, name?: string | undefined, feature_compatibility?: string | undefined, device_graph_only?: boolean | undefined, zone_name?: string | undefined, campaign_service_type?: string | undefined, type?: string | undefined, duration?: StrategyPlanDuration | undefined, budget?: StrategyPlanBudget | undefined, goals?: StrategyPlanGoals | undefined, frequency?: StrategyPlanFrequency | undefined, inventory?: StrategyPlanInventory | undefined, targeting?: StrategyPlanTargeting | undefined, creatives?: StrategyPlanCreatives | undefined}}; export type CreateApiNewStrategyPlansForecastOptions = {baseUrl?: string | undefined, Auth0?: string | undefined, fetch?: typeof fetch | undefined}; export const strategyPlanDuration = z.object({use_campaign_start: z.boolean().optional(), use_campaign_end: z.boolean().optional(), start_date: z.string().nullable().optional(), end_date: z.string().nullable().optional()}); export const strategyPlanBudget = z.object({budget: z.number().nullable().optional(), currency_code: z.string().optional()}); export const strategyPlanGoals = z.object({goal_type: z.enum(["spend", "reach", "cpc", "cpe", "cpa", "roi", "ctr", "vcr", "viewability_rate", "vcpm", ""]).optional(), goal_value: z.number().gte(0).lte(999999999.9999).optional(), min_bid: z.number().gte(0).lte(9999999.99).optional(), max_bid: z.number().gte(0.01).lte(9999999.99).optional(), roi_target: z.number().gte(0).lte(999999999.99).nullable().optional(), bid_min_devices: z.number().int().nullable().optional(), bid_aggressiveness: z.number().int().gte(0).lte(100).optional(), bid_price_is_media_only: z.boolean().optional(), max_bid_wm: z.number().gte(0).lte(9999999.99).nullable().optional(), use_bid_shading: z.boolean().optional()}); export const strategyPlanFrequency = z.object({frequency_type: z.enum(["even", "asap", "no-limit", "t1-optimized"]).nullable().optional(), frequency_interval: z.enum(["hour", "day", "week", "month", "campaign", "not-applicable"]).optional(), frequency_amount: z.number().int().optional(), frequency_optimization: z.boolean().optional()}); export const domainRestriction = z.object({domain: z.string(), target_type: z.enum(["DOMAIN", "APP"])}); export const siteList = z.object({site_list_id: z.number().int(), assigned: z.boolean()}); export const deal = z.object({deal_id: z.number().int()}); export const dealGroup = z.object({deal_group_id: z.number().int()}); export const supplySource = z.object({supply_source_id: z.number().int()}); export const strategyPlanInventory = z.object({run_on_all_pmp: z.boolean(), run_on_all_exchanges: z.boolean(), site_restriction_transparent_urls: z.boolean().optional(), domain_restrictions: z.object({include: z.array(domainRestriction).optional(), exclude: z.array(domainRestriction).optional()}).optional(), site_lists: z.array(siteList).optional(), deals: z.array(deal).optional(), deal_groups: z.array(dealGroup).optional(), supply_sources: z.array(supplySource).optional()}); export const strategyAudienceSegment = z.object({audience_segment_id: z.number().int(), user_cpm: z.number().nullable().optional()}); export const strategyContextualSegment = z.object({targeting_segment_id: z.number().int(), user_cpm: z.number().nullable().optional()}); export const targetingPostalCodes = z.object({restriction: z.string().optional(), codes: z.array(z.string()).optional()}); export const strategyGeofence = z.object({operator: z.enum(["AND", "OR"]).optional(), segments: z.array(z.object({geofence_segment_id: z.number().int().optional(), geofence_segment_factual_id: z.string().optional(), place_list_id: z.number().int().gte(1).lte(2147483647).optional()})).optional()}); export const strategyMyData = z.object({operator: z.enum(["AND", "OR"]).optional(), pixels: z.array(z.object({pixel_id: z.number().int()}))}); export const strategyLocation = z.object({operator: z.enum(["AND", "OR"]).optional(), target_value_id: z.number().int(), code: z.enum(["DMAX", "REGN", "CITY", "COUNTRY"])}); export const strategyTechnology = z.object({operator: z.enum(["AND", "OR"]).optional(), code: z.enum(["BSER", "CSPD", "DVCE", "ISPX", "OSXX", "INVT", "VPSZ", "VLIN", "VCON", "VAUD", "VSKP", "VPLC", "DVMD", "BRLG", "IPTA", "HYPL"]), target_value_id: z.number().int()}); export const targetingIpAddresses = z.object({restriction: z.enum(["INCLUDE", "EXCLUDE", ""]).optional(), codes: z.array(z.string()).optional()}); export const dayPart = z.object({user_time: z.boolean().optional(), start_hour: z.number().int().gte(0).lte(23), end_hour: z.number().int().gte(0).lte(23), days: z.array(z.enum(["M", "T", "W", "R", "F", "S", "U"]))}); export const strategyPlanTargeting = z.object({fold_position: z.array(z.enum(["ABOVE", "BELOW", "UNCATEGORIZED"])).nullable().optional(), audience: z.object({include: z.array(z.object({operator: z.enum(["AND", "OR"]).optional(), segments: z.array(strategyAudienceSegment).optional()})).optional(), exclude: z.object({operator: z.enum(["AND", "OR"]).optional(), segments: z.array(strategyAudienceSegment).optional()}).optional()}).optional(), contextual: z.object({include: z.array(z.object({code: z.string().optional(), operator: z.enum(["AND", "OR"]).optional(), segments: z.array(strategyContextualSegment).optional()})).optional(), exclude: z.object({code: z.string().optional(), operator: z.enum(["AND", "OR"]).optional(), segments: z.array(strategyContextualSegment)}).optional()}).optional(), postal_codes: targetingPostalCodes.optional(), geofence: z.object({include: strategyGeofence.optional(), exclude: strategyGeofence.optional()}).optional(), my_data: z.object({include: strategyMyData.optional(), exclude: strategyMyData.optional()}).optional(), location: z.object({include: z.array(strategyLocation).optional(), exclude: z.array(strategyLocation).optional()}).optional(), technology: z.object({include: z.array(strategyTechnology).optional(), exclude: z.array(strategyTechnology).optional()}).optional(), ip_addresses: targetingIpAddresses.optional(), day_parts: z.array(dayPart).optional(), recency: z.array(z.object({pixel_id: z.number().int(), from_hour: z.number().int(), to_hour: z.number().int()})).optional(), language_codes: z.array(z.object({code: z.string().optional(), name: z.string().optional()})).optional()}); export const strategyPlanCreatives = z.object({ad_expandable: z.boolean().nullable(), ad_formats: z.array(z.string()).nullable(), ad_sizes: z.array(z.string()).nullable()}); export const createApiNewStrategyPlansForecastResponse = z.object({data: z.object({campaign_start_date: z.string().optional(), campaign_end_date: z.string().optional(), campaign_zone_name: z.string().optional(), name: z.string().max(128).optional(), feature_compatibility: z.string().max(1024).optional(), device_graph_only: z.boolean().optional(), zone_name: z.string().optional(), campaign_service_type: z.string().optional(), type: z.string().optional(), duration: strategyPlanDuration.optional(), budget: strategyPlanBudget.optional(), goals: strategyPlanGoals.optional(), frequency: strategyPlanFrequency.optional(), inventory: strategyPlanInventory.optional(), targeting: strategyPlanTargeting.optional(), creatives: strategyPlanCreatives.optional(), id: z.number().int().optional(), version: z.number().int().optional(), campaign_id: z.number().int().optional()}).optional(), meta: z.object({status: z.string().optional()}).optional()}); 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 }; /** * Post Ephemeral New Strategy Plan to Run a Forecast * * POST /new_strategy_plans/forecast */ export const createApiNewStrategyPlansForecast = async (args: CreateApiNewStrategyPlansForecastArgs, options?: CreateApiNewStrategyPlansForecastOptions) => { const {baseUrl = "https://api.mediamath.com/api/v3.0", fetch: fetchFn = fetch, Auth0} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (Auth0 !== undefined) headers.set('authorization', `Bearer ${Auth0}`) const url = `${baseUrl.replace(/\/+$/, '')}/new_strategy_plans/forecast${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", 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(createApiNewStrategyPlansForecastResponse, await res.json()) };