import {z} from 'zod' export type AdCollectionsHeaderType = 'SHOP_THIS_COLLECTION' | 'EXPLORE_THIS_COLLECTION' | 'NO_HEADER' | 'null' | null; export type CreativeType = 'REGULAR' | 'VIDEO' | 'SHOPPING' | 'CAROUSEL' | 'MAX_VIDEO' | 'SHOP_THE_PIN' | 'COLLECTION' | 'IDEA' | 'SHOWCASE' | 'QUIZ' | 'COLLAGE' | 'MAX_WIDTH_REGULAR_COLLECTION' | 'MAX_WIDTH_VIDEO_COLLECTION' | 'APP'; export type CustomizableCTAType = 'GET_OFFER' | 'LEARN_MORE' | 'ORDER_NOW' | 'SHOP_NOW' | 'SIGN_UP' | 'SUBSCRIBE' | 'BUY_NOW' | 'CONTACT_US' | 'GET_QUOTE' | 'VISIT_SITE' | 'APPLY_NOW' | 'BOOK_NOW' | 'REQUEST_DEMO' | 'REGISTER_NOW' | 'FIND_A_DEALER' | 'ADD_TO_CART' | 'WATCH_NOW' | 'READ_MORE' | 'BUY_TICKETS' | 'DONATE_NOW' | 'DOWNLOAD' | 'EXPLORE_MORE' | 'FIND_A_LOCATION' | 'FIND_RETAILERS' | 'GET_DEAL' | 'GET_RECIPE' | 'GET_SHOWTIMES' | 'ON_SALE' | 'PLAY_GAME' | 'TRY_IT' | 'TAKE_A_PEEK' | 'null' | null; export type DisclosureType = 'NO_DISCLOSURE' | 'PRESCRIBING_INFORMATION' | 'PRESCRIBING_INFORMATION_BOX_WARNING' | 'IMPORTANT_SAFETY_INFO' | 'MED_GUIDE' | 'PATIENT_INFORMATION' | 'null' | null; export type GridClickType = 'CLOSEUP' | 'DIRECT_TO_DESTINATION' | null; export type QuizPinOption = {id?: number | undefined, text?: string | undefined} | null; export type QuizPinQuestion = {options?: Array | undefined, question_id?: number | undefined, question_text?: string | undefined} | null; export type QuizPinResult = {android_deep_link?: string | undefined, destination_url?: string | undefined, ios_deep_link?: string | undefined, organic_pin_id?: string | undefined, result_id?: number | undefined} | null; export type TieBreakerType = 'RANDOM' | 'CUSTOM'; export type QuizPinData = {questions?: Array | undefined, results?: Array | undefined, tie_breaker_custom_result?: QuizPinResult | undefined, tie_breaker_type?: TieBreakerType | 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 AdBatchUpdate = {ad_group_id?: string | undefined, android_deep_link?: (string | null) | undefined, carousel_android_deep_links?: (Array | null) | undefined, carousel_destination_urls?: (Array | null) | undefined, carousel_ios_deep_links?: (Array | null) | undefined, click_tracking_url?: (string | null) | undefined, collection_items_destination_url_template?: (string | null) | undefined, collections_header_type?: (AdCollectionsHeaderType | null) | undefined, creative_type?: CreativeType | undefined, customizable_cta_type?: CustomizableCTAType | undefined, destination_url?: (string | null) | undefined, disclosure_type?: DisclosureType | undefined, disclosure_url?: (string | null) | undefined, grid_click_type?: GridClickType | undefined, id: string, ios_deep_link?: (string | null) | undefined, is_carting?: boolean | undefined, is_collage_accepted_terms?: boolean | undefined, is_collage_single_destination?: boolean | undefined, is_pin_deleted?: boolean | undefined, is_removable?: boolean | undefined, lead_form_id?: (string | null) | undefined, name?: (string | null) | undefined, pin_id?: string | undefined, quiz_pin_data?: (QuizPinData | null) | undefined, status?: EntityStatus | undefined, tracking_urls?: TrackingUrls | undefined, view_tracking_url?: (string | null) | undefined}; export type AdBatchUpdateRequest = Array; export type PatchApiAdAccountsAdAccountIdAdsArgs = {ad_account_id: string, body: AdBatchUpdateRequest}; export type PatchApiAdAccountsAdAccountIdAdsOptions = {baseUrl?: string | undefined, pinterestOauth2?: string | undefined, fetch?: typeof fetch | undefined}; export const cartingPlatformType = z.number().int().gte(1).lte(2); export const cartingRetailer = z.object({retailer_id: z.string(), retailer_name: z.string()}); export const cartingProduct = z.object({carting_product_id: z.string(), display_preferred_retailers_only: z.boolean().optional(), display_product_price: z.boolean().optional(), preferred_retailers: z.array(cartingRetailer).optional(), randomize_preferred_retailers: z.boolean().optional()}); export const adCollectionsHeaderType = z.enum(["SHOP_THIS_COLLECTION", "EXPLORE_THIS_COLLECTION", "NO_HEADER", "null"]).nullable(); export const creativeType = z.enum(["REGULAR", "VIDEO", "SHOPPING", "CAROUSEL", "MAX_VIDEO", "SHOP_THE_PIN", "COLLECTION", "IDEA", "SHOWCASE", "QUIZ", "COLLAGE", "MAX_WIDTH_REGULAR_COLLECTION", "MAX_WIDTH_VIDEO_COLLECTION", "APP"]); export const customizableCTAType = z.enum(["GET_OFFER", "LEARN_MORE", "ORDER_NOW", "SHOP_NOW", "SIGN_UP", "SUBSCRIBE", "BUY_NOW", "CONTACT_US", "GET_QUOTE", "VISIT_SITE", "APPLY_NOW", "BOOK_NOW", "REQUEST_DEMO", "REGISTER_NOW", "FIND_A_DEALER", "ADD_TO_CART", "WATCH_NOW", "READ_MORE", "BUY_TICKETS", "DONATE_NOW", "DOWNLOAD", "EXPLORE_MORE", "FIND_A_LOCATION", "FIND_RETAILERS", "GET_DEAL", "GET_RECIPE", "GET_SHOWTIMES", "ON_SALE", "PLAY_GAME", "TRY_IT", "TAKE_A_PEEK", "null"]).nullable(); export const disclosureType = z.enum(["NO_DISCLOSURE", "PRESCRIBING_INFORMATION", "PRESCRIBING_INFORMATION_BOX_WARNING", "IMPORTANT_SAFETY_INFO", "MED_GUIDE", "PATIENT_INFORMATION", "null"]).nullable(); export const gridClickType = z.enum(["CLOSEUP", "DIRECT_TO_DESTINATION"]).nullable(); export const quizPinOption = z.object({id: z.number().optional(), text: z.string().optional()}).nullable(); export const quizPinQuestion = z.object({options: z.array(quizPinOption).optional(), question_id: z.number().optional(), question_text: z.string().optional()}).nullable(); export const quizPinResult = z.object({android_deep_link: z.string().optional(), destination_url: z.string().optional(), ios_deep_link: z.string().optional(), organic_pin_id: z.string().optional(), result_id: z.number().optional()}).nullable(); export const tieBreakerType = z.enum(["RANDOM", "CUSTOM"]); export const quizPinData = z.object({questions: z.array(quizPinQuestion).optional(), results: z.array(quizPinResult).optional(), tie_breaker_custom_result: quizPinResult.optional(), tie_breaker_type: tieBreakerType.optional()}).nullable(); export const adDisapprovalReasons = z.enum(["HASHTAGS", "PROMOTIONS_AND_PRICES", "TARGETING", "LANDING_PAGE", "CAPS_AND_SYMBOLS", "SHOCKING", "WEIGHT_LOSS", "PROHIBITED_PRODUCT", "AUTHENTICITY", "NUDITY", "CONFUSING_DESIGN", "URGENCY", "RATINGS", "APP", "ALCOHOL", "CONTESTS", "POLITICAL", "OTHER", "IMAGE", "NAR", "INCONSISTENT", "CLICKBAIT", "NO_DESCRIPTION", "LOW_QUALITY", "EXAGGERATED_CLAIMS", "PINTEREST_BRAND", "ALCOHOL_NO_SALE", "LANDING_PAGE_SPEED", "LANDING_PAGE_HARDWALL", "LANDING_PAGE_BROKEN", "LANDING_PAGE_QUALITY", "OUT_OF_STOCK", "IMAGE_LOW_QUALITY", "IMAGE_BUSY", "IMAGE_POORLY_EDITED", "IMAGE_BEFORE_AFTER", "UGC", "FAKE_BUTTONS", "WEAPONS", "SENSITIVE", "UNACCEPTABLE_BUSINESS", "SUSPICIOUS_CLAIMS", "PHARMA", "SUSPICIOUS_SUPPLEMENTS", "ILLEGAL_RECREATIONAL_DRUG", "LOW_QUALITY_LANDING_PAGE", "RESTRICTED_HEALTHCARE", "INCONSISTENT_LANG_FR"]); export const adReviewStatus = z.enum(["OTHER", "PENDING", "REJECTED", "APPROVED"]); export const entityStatus = z.enum(["ACTIVE", "PAUSED", "ARCHIVED", "DRAFT", "DELETED_DRAFT"]); export const pinPromotionSummaryStatus = z.enum(["APPROVED", "PAUSED", "PENDING", "REJECTED", "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 ad = z.object({ad_account_id: z.string(), ad_group_id: z.string(), android_deep_link: z.string().nullable().optional(), campaign_id: z.string(), carousel_android_deep_links: z.array(z.string()).nullable().optional(), carousel_destination_urls: z.array(z.string()).nullable().optional(), carousel_ios_deep_links: z.array(z.string()).nullable().optional(), carting_platform_type: cartingPlatformType.optional(), carting_products: z.array(cartingProduct).optional(), click_tracking_url: z.string().nullable().optional(), collection_items_destination_url_template: z.string().nullable().optional(), collections_header_type: adCollectionsHeaderType.nullable().optional(), created_time: z.number().int().optional(), creative_type: creativeType, customizable_cta_type: customizableCTAType.optional(), destination_url: z.string().nullable().optional(), disclosure_type: disclosureType.optional(), disclosure_url: z.string().nullable().optional(), grid_click_type: gridClickType.optional(), id: z.string().max(18), ios_deep_link: z.string().nullable().optional(), is_carting: z.boolean().optional(), is_collage_accepted_terms: z.boolean().optional(), is_collage_single_destination: z.boolean().optional(), is_pin_deleted: z.boolean().optional(), is_removable: z.boolean().optional(), lead_form_id: z.string().nullable().optional(), name: z.string().nullable().optional(), pin_id: z.string(), quiz_pin_data: quizPinData.nullable().optional(), rejected_reasons: z.array(adDisapprovalReasons), rejection_labels: z.array(z.string()), review_status: adReviewStatus, status: entityStatus.optional(), summary_status: pinPromotionSummaryStatus, tracking_urls: trackingUrls.optional(), type: z.string(), updated_time: z.number().int().optional(), view_tracking_url: z.string().nullable().optional()}); export const pinterestLibError = z.object({code: z.number().int(), message: z.string()}); export const adBatchItem = z.object({data: ad.optional(), exceptions: pinterestLibError.optional()}); export const adBatchWriteResponseModel = z.object({items: z.array(adBatchItem)}); 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 ads * * PATCH /ad_accounts/{ad_account_id}/ads */ export const patchApiAdAccountsAdAccountIdAds = async (args: PatchApiAdAccountsAdAccountIdAdsArgs, options?: PatchApiAdAccountsAdAccountIdAdsOptions) => { 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))}/ads${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(adBatchWriteResponseModel, await res.json()) };