import {z} from 'zod' export type MobileAppPlatform = 'IOS' | 'ANDROID'; export type AgeBucketMultipliersAdditionalProperties = number; export type TargetingSpecAgeBucket = '18-24' | '19+' | '20+' | '21+' | '25-34' | '35-44' | '45-49' | '50-54' | '55-64' | '65+'; export type AgeBucketMultipliers = {AGE_BUCKET?: TargetingSpecAgeBucket | undefined} | {[key: string]: AgeBucketMultipliersAdditionalProperties} | null; export type TargetingSpecAppType = 'android_mobile' | 'android_tablet' | 'ipad' | 'iphone' | 'web' | 'web_mobile'; export type AppTypeMultipliers = {APP_TYPE?: TargetingSpecAppType | undefined} | {[key: string]: number} | null; export type CampaignAudienceMultipliersAdditionalProperties = number; export type CampaignAudienceMultipliers = {AUDIENCE_ID?: string | undefined} | {[key: string]: CampaignAudienceMultipliersAdditionalProperties}; export type FreqBidMultiplierTimeWindow = 'WEEK' | 'MONTH' | 'null' | null; export type FrequencyMultipliers = {IMPRESSION_COUNT?: string | undefined} | {[key: string]: number} | null; export type GenderMultipliersAdditionalProperties = number; export type TargetingSpecGender = 'unknown' | 'male' | 'female'; export type GenderMultipliers = {GENDER?: TargetingSpecGender | undefined} | {[key: string]: GenderMultipliersAdditionalProperties} | null; export type PlacementType = 'SEARCH' | 'BROWSE' | 'RELATED_PINS'; export type PlacementMultipliers = {PLACEMENT?: PlacementType | undefined} | {[key: string]: number} | null; export type CampaignBidOptionsUpdateMaskItems = 'AUDIENCE' | 'APP_TYPE' | 'PLACEMENT' | 'GENDER' | 'AGE_BUCKET' | 'FREQUENCY'; export type CampaignBidOptionsUpdate = {age_bucket_multipliers?: AgeBucketMultipliers | undefined, app_type_multipliers?: AppTypeMultipliers | undefined, audience_multipliers?: CampaignAudienceMultipliers | undefined, freq_bid_multiplier_time_window?: (FreqBidMultiplierTimeWindow | null) | undefined, frequency_multipliers?: (FrequencyMultipliers | null) | undefined, gender_multipliers?: GenderMultipliers | undefined, placement_multipliers?: PlacementMultipliers | undefined, update_mask: Array} | null; export type IntendedPromotionType = 'LEGACY' | 'STANDARD_AD' | 'CATALOG'; export type ConversionObjectiveType = 'AWARENESS' | 'CONSIDERATION' | 'WEB_CONVERSION' | 'CATALOG_SALES' | 'VIDEO_COMPLETION' | 'APP_INSTALL' | 'SALES' | 'LEADS' | 'CTV_CONSIDERATION'; export type PerformancePlusCampaignSettings = {boost_prospecting_ad_group_bid?: boolean | undefined, pinner_list_exclusions?: Array | undefined} | null; export type EntityStatus = 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT' | 'DELETED_DRAFT'; export type TrackingUrls = {audience_verification?: Array | undefined, buyable_button?: Array | undefined, click?: Array | undefined, engagement?: Array | undefined, impression?: Array | undefined} | null; export type CampaignBatchUpdateItem = {ad_account_id?: string | undefined, app_id?: string | undefined, app_platform?: MobileAppPlatform | undefined, bid_options?: CampaignBidOptionsUpdate | undefined, daily_spend_cap?: (number | null) | undefined, default_ad_group_budget_in_micro_currency?: (number | null) | undefined, end_time?: (number | null) | undefined, id: string, intended_promotion_type?: IntendedPromotionType | undefined, is_automated_campaign?: (boolean | null) | undefined, is_campaign_budget_optimization?: (boolean | null) | undefined, is_flexible_daily_budgets?: (boolean | null) | undefined, is_ltv_optimized?: boolean | undefined, is_performance_plus?: boolean | undefined, is_top_of_search?: boolean | undefined, lifetime_spend_cap?: (number | null) | undefined, name?: string | undefined, objective_type?: ConversionObjectiveType | undefined, order_line_id?: (string | null) | undefined, performance_plus_campaign_settings?: (PerformancePlusCampaignSettings | null) | undefined, start_time?: (number | null) | undefined, status?: EntityStatus | undefined, tracking_urls?: (TrackingUrls | null) | undefined}; export type CampaignBatchUpdateRequest = Array; export type PatchApiAdAccountsAdAccountIdCampaignsArgs = {ad_account_id: string, body: CampaignBatchUpdateRequest}; export type PatchApiAdAccountsAdAccountIdCampaignsOptions = {baseUrl?: string | undefined, pinterestOauth2?: string | undefined, fetch?: typeof fetch | undefined}; export const ageBucketMultipliersAdditionalProperties = z.number(); export const targetingSpecAgeBucket = z.enum(["18-24", "19+", "20+", "21+", "25-34", "35-44", "45-49", "50-54", "55-64", "65+"]); export const ageBucketMultipliers = z.object({AGE_BUCKET: targetingSpecAgeBucket.optional()}).and(z.record(z.string(), ageBucketMultipliersAdditionalProperties)).nullable(); export const targetingSpecAppType = z.enum(["android_mobile", "android_tablet", "ipad", "iphone", "web", "web_mobile"]); export const appTypeMultipliers = z.object({APP_TYPE: targetingSpecAppType.optional()}).and(z.record(z.string(), z.number())).nullable(); export const campaignAudienceMultipliersAdditionalProperties = z.number().gte(0).lte(10); export const campaignAudienceMultipliers = z.object({AUDIENCE_ID: z.string().optional()}).and(z.record(z.string(), campaignAudienceMultipliersAdditionalProperties)); export const freqBidMultiplierTimeWindow = z.enum(["WEEK", "MONTH", "null"]).nullable(); export const frequencyMultipliers = z.object({IMPRESSION_COUNT: z.string().optional()}).and(z.record(z.string(), z.number())).nullable(); export const genderMultipliersAdditionalProperties = z.number(); export const targetingSpecGender = z.enum(["unknown", "male", "female"]); export const genderMultipliers = z.object({GENDER: targetingSpecGender.optional()}).and(z.record(z.string(), genderMultipliersAdditionalProperties)).nullable(); export const placementType = z.enum(["SEARCH", "BROWSE", "RELATED_PINS"]); export const placementMultipliers = z.object({PLACEMENT: placementType.optional()}).and(z.record(z.string(), z.number())).nullable(); export const campaignBidOptions = z.object({age_bucket_multipliers: ageBucketMultipliers.optional(), app_type_multipliers: appTypeMultipliers.optional(), audience_multipliers: campaignAudienceMultipliers.optional(), freq_bid_multiplier_time_window: freqBidMultiplierTimeWindow.nullable().optional(), frequency_multipliers: frequencyMultipliers.nullable().optional(), gender_multipliers: genderMultipliers.optional(), placement_multipliers: placementMultipliers.optional()}).nullable(); export const intendedPromotionType = z.enum(["LEGACY", "STANDARD_AD", "CATALOG"]); export const campaignObjectiveType = z.enum(["AWARENESS", "CONSIDERATION", "VIDEO_VIEW", "WEB_CONVERSION", "CATALOG_SALES", "WEB_SESSIONS", "VIDEO_COMPLETION", "APP_INSTALL", "SALES", "LEADS", "CTV_CONSIDERATION"]); export const performancePlusCampaignSettings = z.object({boost_prospecting_ad_group_bid: z.boolean().optional(), pinner_list_exclusions: z.array(z.string()).optional()}).nullable(); export const nullableEntityStatus = z.enum(["ACTIVE", "PAUSED", "ARCHIVED", "DRAFT", "DELETED_DRAFT", "null"]).nullable(); export const summaryStatus = z.enum(["RUNNING", "PAUSED", "NOT_STARTED", "COMPLETED", "ADVERTISER_DISABLED", "ARCHIVED", "DRAFT", "DELETED_DRAFT"]); export const trackingUrls = z.object({audience_verification: z.array(z.string()).optional(), buyable_button: z.array(z.string()).optional(), click: z.array(z.string()).optional(), engagement: z.array(z.string()).optional(), impression: z.array(z.string()).optional()}).nullable(); export const campaignBatchResponseData = z.object({ad_account_id: z.string().optional(), bid_options: campaignBidOptions.optional(), created_time: z.number().int().optional(), daily_spend_cap: z.number().int().nullable().optional(), default_ad_group_budget_in_micro_currency: z.number().int().nullable().optional(), end_time: z.number().int().nullable().optional(), id: z.string().optional(), intended_promotion_type: intendedPromotionType.optional(), is_automated_campaign: z.boolean().nullable().optional(), is_campaign_budget_optimization: z.boolean().nullable().optional(), is_carting: z.boolean().optional(), is_flexible_daily_budgets: z.boolean().nullable().optional(), is_ltv_optimized: z.boolean().optional(), is_performance_plus: z.boolean().optional(), is_top_of_search: z.boolean().optional(), lifetime_spend_cap: z.number().int().nullable().optional(), name: z.string().optional(), objective_type: campaignObjectiveType.optional(), order_line_id: z.string().nullable().optional(), performance_plus_campaign_settings: performancePlusCampaignSettings.nullable().optional(), start_time: z.number().int().nullable().optional(), status: nullableEntityStatus.nullable().optional(), summary_status: summaryStatus.optional(), tracking_urls: trackingUrls.nullable().optional(), type: z.string().optional(), updated_time: z.number().int().optional()}); export const exception = z.object({code: z.number().int().optional(), message: z.string()}); export const campaignBatchItem = z.object({data: campaignBatchResponseData.optional(), exceptions: z.array(exception).optional()}); export const campaignBatchWriteResponseModel = z.object({items: z.array(campaignBatchItem)}); 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 campaigns * * PATCH /ad_accounts/{ad_account_id}/campaigns */ export const patchApiAdAccountsAdAccountIdCampaigns = async (args: PatchApiAdAccountsAdAccountIdCampaignsArgs, options?: PatchApiAdAccountsAdAccountIdCampaignsOptions) => { const {baseUrl = "https://api.pinterest.com/v5", fetch: fetchFn = fetch, pinterestOauth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (pinterestOauth2 !== undefined) headers.set('authorization', `Bearer ${pinterestOauth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/ad_accounts/${encodeURIComponent(String(args.ad_account_id))}/campaigns${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "PATCH", 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(campaignBatchWriteResponseModel, await res.json()) };