import {z} from 'zod' export type PinterestLibPaginationOrder = 'ASCENDING' | 'DESCENDING'; export type CampaignIdType = string; export type EntityStatus = 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT' | 'DELETED_DRAFT'; export type GetApiAdAccountsAdAccountIdCampaignsArgs = {bookmark?: string | undefined, page_size?: number | undefined, order?: PinterestLibPaginationOrder | undefined, ad_account_id: string, campaign_ids?: Array | undefined, entity_statuses?: Array | undefined}; export type GetApiAdAccountsAdAccountIdCampaignsOptions = {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 entityStatus = z.enum(["ACTIVE", "PAUSED", "ARCHIVED", "DRAFT", "DELETED_DRAFT"]); 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 campaign = 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().max(18), 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, order_line_id: z.string().nullable().optional(), performance_plus_campaign_settings: performancePlusCampaignSettings.nullable().optional(), start_time: z.number().int().nullable().optional(), status: entityStatus.optional(), summary_status: summaryStatus.optional(), tracking_urls: trackingUrls.nullable().optional(), type: z.string().optional(), updated_time: z.number().int().optional()}); export const getApiAdAccountsAdAccountIdCampaignsResponse = z.object({bookmark: z.string().nullable().optional(), items: z.array(campaign)}); 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 }; /** * List campaigns * * GET /ad_accounts/{ad_account_id}/campaigns * * Also accepts auth: client_credentials */ export const getApiAdAccountsAdAccountIdCampaigns = async (args: GetApiAdAccountsAdAccountIdCampaignsArgs, options?: GetApiAdAccountsAdAccountIdCampaignsOptions) => { const {baseUrl = "https://api.pinterest.com/v5", fetch: fetchFn = fetch, pinterestOauth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.bookmark != null) query.append("bookmark", String(args.bookmark)) if (args.page_size != null) query.append("page_size", String(args.page_size)) if (args.order != null) query.append("order", String(args.order)) for (const item of args.campaign_ids ?? []) query.append("campaign_ids", String(item)) for (const item of args.entity_statuses ?? []) query.append("entity_statuses", String(item)) 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: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiAdAccountsAdAccountIdCampaignsResponse, await res.json()) };