import {z} from 'zod' export type PinterestLibPaginationOrder = 'ASCENDING' | 'DESCENDING'; export type CampaignIdType = string; export type PinterestLibIntegerFormatType = string; export type EntityStatus = 'ACTIVE' | 'PAUSED' | 'ARCHIVED' | 'DRAFT' | 'DELETED_DRAFT'; export type GetApiAdAccountsAdAccountIdAdsArgs = {bookmark?: string | undefined, page_size?: number | undefined, order?: PinterestLibPaginationOrder | undefined, ad_account_id: string, campaign_ids?: Array | undefined, ad_group_ids?: Array | undefined, ad_ids?: Array | undefined, entity_statuses?: Array | undefined}; export type GetApiAdAccountsAdAccountIdAdsOptions = {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 getApiAdAccountsAdAccountIdAdsResponse = z.object({bookmark: z.string().nullable().optional(), items: z.array(ad)}); 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 ads * * GET /ad_accounts/{ad_account_id}/ads * * Also accepts auth: client_credentials */ export const getApiAdAccountsAdAccountIdAds = async (args: GetApiAdAccountsAdAccountIdAdsArgs, options?: GetApiAdAccountsAdAccountIdAdsOptions) => { 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.ad_group_ids ?? []) query.append("ad_group_ids", String(item)) for (const item of args.ad_ids ?? []) query.append("ad_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))}/ads${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(getApiAdAccountsAdAccountIdAdsResponse, await res.json()) };