import {z} from 'zod' export type LookbackPeriodOptions = '1d' | '14d'; export type SourcePlatformOptions = 'WEB' | 'MOBILE' | 'MOBILE_ANDROID' | 'MOBILE_IOS' | 'OFFLINE' | 'PINTEREST_WEB' | 'PINTEREST_ANDROID' | 'PINTEREST_IOS' | 'POINT_OF_SALE'; export type IngestionSourceOptions = 'TAG' | 'MMP' | 'FILE_UPLOAD' | 'CONVERSIONS_API' | 'NATIVE'; export type GetApiAdAccountsAdAccountIdConversionEqsArgs = {lookback_period: LookbackPeriodOptions, source_platform?: SourcePlatformOptions | undefined, ingestion_source?: IngestionSourceOptions | undefined, ad_account_id: string}; export type GetApiAdAccountsAdAccountIdConversionEqsOptions = {baseUrl?: string | undefined, pinterestOauth2?: string | undefined, fetch?: typeof fetch | undefined}; export const ingestionSourceOptions = z.enum(["TAG", "MMP", "FILE_UPLOAD", "CONVERSIONS_API", "NATIVE"]); export const lookbackPeriodOptions = z.enum(["1d", "14d"]); export const overallStatusOptions = z.enum(["NEEDS_IMPROVEMENT", "FAIR", "GOOD"]); export const qualityComponentIssue = z.object({id: z.string(), name: z.string(), reason: z.string()}); export const qualityComponentDetails = z.object({coverage: z.number(), issues: z.array(qualityComponentIssue).optional(), overlap: z.number().optional()}); export const qualityComponents = z.object({advertiser_external_id: z.record(z.string(), qualityComponentDetails).optional(), click_id_epik: z.record(z.string(), qualityComponentDetails).optional(), external_event_id: z.record(z.string(), qualityComponentDetails).optional(), hashed_email: z.record(z.string(), qualityComponentDetails).optional(), hashed_maid: z.record(z.string(), qualityComponentDetails).optional(), ip_address: z.record(z.string(), qualityComponentDetails).optional(), order_id: z.record(z.string(), qualityComponentDetails).optional(), order_value: z.record(z.string(), qualityComponentDetails).optional(), product_id: z.record(z.string(), qualityComponentDetails).optional(), source_url: z.record(z.string(), qualityComponentDetails).optional(), user_agent: z.record(z.string(), qualityComponentDetails).optional()}); export const sourcePlatformOptions = z.enum(["WEB", "MOBILE", "MOBILE_ANDROID", "MOBILE_IOS", "OFFLINE", "PINTEREST_WEB", "PINTEREST_ANDROID", "PINTEREST_IOS", "POINT_OF_SALE"]); export const eventQualityScore = z.object({ingestion_source: ingestionSourceOptions, lookback_period: lookbackPeriodOptions, overall_status: overallStatusOptions, quality_components: qualityComponents, source_platform: sourcePlatformOptions}); export const getApiAdAccountsAdAccountIdConversionEqsResponse = z.array(eventQualityScore); 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 }; /** * Get event quality score (EQS) * * GET /ad_accounts/{ad_account_id}/conversion_eqs * * Also accepts auth: client_credentials */ export const getApiAdAccountsAdAccountIdConversionEqs = async (args: GetApiAdAccountsAdAccountIdConversionEqsArgs, options?: GetApiAdAccountsAdAccountIdConversionEqsOptions) => { 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.lookback_period != null) query.append("lookback_period", String(args.lookback_period)) if (args.source_platform != null) query.append("source_platform", String(args.source_platform)) if (args.ingestion_source != null) query.append("ingestion_source", String(args.ingestion_source)) if (pinterestOauth2 !== undefined) headers.set('authorization', `Bearer ${pinterestOauth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/ad_accounts/${encodeURIComponent(String(args.ad_account_id))}/conversion_eqs${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(getApiAdAccountsAdAccountIdConversionEqsResponse, await res.json()) };