import {z} from 'zod' export type InvoiceStatus = 'DRAFT' | 'SENT' | 'SCHEDULED' | 'PAID' | 'MARKED_AS_PAID' | 'CANCELLED' | 'REFUNDED' | 'PARTIALLY_PAID' | 'PARTIALLY_REFUNDED' | 'MARKED_AS_REFUNDED' | 'UNPAID' | 'PAYMENT_PENDING' | 'AUTO_CANCELLED' | 'PAID_EXTERNAL' | 'REFUNDED_EXTERNAL' | 'SHARED'; export type CurrencyCode = unknown; export type DateTime = unknown; export type FileReference = {id?: string | undefined, reference_url?: string | undefined, content_type?: string | undefined, create_time?: DateTime | undefined, size?: string | undefined}; export type FileReferenceList = Array; export type DateNoTime = unknown; export type PaymentTermType = 'DUE_ON_RECEIPT' | 'DUE_ON_DATE_SPECIFIED' | 'NET_10' | 'NET_15' | 'NET_30' | 'NET_45' | 'NET_60' | 'NET_90' | 'NO_DUE_DATE'; export type InvoicePaymentTerm = {term_type?: PaymentTermType | undefined, due_date?: DateNoTime | undefined}; export type InvoiceCreationFlow = 'MULTIPLE_RECIPIENTS_GROUP' | 'BATCH' | 'REGULAR_SINGLE'; export type Metadata = {create_time?: DateTime | undefined, created_by?: string | undefined, last_update_time?: DateTime | undefined, last_updated_by?: string | undefined, cancel_time?: DateTime | undefined, cancelled_by?: string | undefined, first_sent_time?: DateTime | undefined, last_sent_time?: DateTime | undefined, last_sent_by?: string | undefined, created_by_flow?: InvoiceCreationFlow | undefined, recipient_view_url?: string | undefined, invoicer_view_url?: string | undefined}; export type InvoiceDetail = {reference?: string | undefined, currency_code: CurrencyCode, note?: string | undefined, terms_and_conditions?: string | undefined, memo?: string | undefined, attachments?: FileReferenceList | undefined, invoice_number?: string | undefined, invoice_date?: DateNoTime | undefined, payment_term?: InvoicePaymentTerm | undefined, metadata?: Metadata | undefined}; export type Name = {prefix?: string | undefined, given_name?: string | undefined, surname?: string | undefined, middle_name?: string | undefined, suffix?: string | undefined, alternate_full_name?: string | undefined, full_name?: string | undefined}; export type CountryCode = unknown; export type AddressDetails = {street_number?: string | undefined, street_name?: string | undefined, street_type?: string | undefined, delivery_service?: string | undefined, building_name?: string | undefined, sub_building?: string | undefined}; export type AddressPortable = {address_line_1?: string | undefined, address_line_2?: string | undefined, address_line_3?: string | undefined, admin_area_4?: string | undefined, admin_area_3?: string | undefined, admin_area_2?: string | undefined, admin_area_1?: string | undefined, postal_code?: string | undefined, country_code: CountryCode, address_details?: AddressDetails | undefined}; export type RestrictiveEmailAddress = string; export type PhoneType = 'FAX' | 'HOME' | 'MOBILE' | 'OTHER' | 'PAGER'; export type PhoneDetail = {country_code: string, national_number: string, extension_number?: string | undefined, phone_type: PhoneType}; export type PhoneDetailList = Array; export type InvoicerInfo = {business_name?: string | undefined, name?: Name | undefined, address?: AddressPortable | undefined, email_address?: RestrictiveEmailAddress | undefined, phones?: PhoneDetailList | undefined, website?: string | undefined, tax_id?: string | undefined, additional_notes?: string | undefined, logo_url?: string | undefined}; export type DefinitionsPhoneDetailList = Array; export type Language = unknown; export type BillingInfo = {business_name?: string | undefined, name?: Name | undefined, address?: AddressPortable | undefined, email_address?: RestrictiveEmailAddress | undefined, phones?: DefinitionsPhoneDetailList | undefined, additional_info?: string | undefined, language?: Language | undefined}; export type ContactNameAddress = {business_name?: string | undefined, name?: Name | undefined, address?: AddressPortable | undefined}; export type RecipientInfo = {billing_info?: BillingInfo | undefined, shipping_info?: ContactNameAddress | undefined}; export type RecipientInfoList = Array; export type EmailAddress = unknown; export type EmailAddressList = Array; export type Money = {currency_code: CurrencyCode, value: string}; export type Percentage = unknown; export type Tax = {name: string, percent: Percentage, amount?: Money | undefined, tax_note?: string | undefined}; export type Discount = {percent?: Percentage | undefined, amount?: Money | undefined}; export type UnitOfMeasure = 'QUANTITY' | 'HOURS' | 'AMOUNT'; export type Item = {id?: string | undefined, name: string, description?: string | undefined, quantity: string, unit_amount: Money, tax?: Tax | undefined, item_date?: DateNoTime | undefined, discount?: Discount | undefined, unit_of_measure?: UnitOfMeasure | undefined}; export type ItemList = Array; export type PartialPayment = {allow_partial_payment?: boolean | undefined, minimum_amount_due?: Money | undefined}; export type Configuration = {tax_calculated_after_discount?: boolean | undefined, tax_inclusive?: boolean | undefined, allow_tip?: boolean | undefined, partial_payment?: PartialPayment | undefined, has_conditional_rule?: boolean | undefined, template_id?: string | undefined}; export type AggregatedDiscount = {invoice_discount?: Discount | undefined, item_discount?: Money | undefined}; export type ShippingCost = {amount?: Money | undefined, tax?: Tax | undefined}; export type CustomAmount = {label: string, amount?: Money | undefined}; export type AmountWithBreakdown = {item_total?: Money | undefined, discount?: AggregatedDiscount | undefined, tax_total?: Money | undefined, shipping?: ShippingCost | undefined, custom?: CustomAmount | undefined}; export type AmountSummaryDetail = {currency_code?: CurrencyCode | undefined, value?: string | undefined, breakdown?: AmountWithBreakdown | undefined}; export type PaymentType = 'PAYPAL' | 'EXTERNAL'; export type PaymentMethod = 'BANK_TRANSFER' | 'CASH' | 'CHECK' | 'CREDIT_CARD' | 'DEBIT_CARD' | 'PAYPAL' | 'WIRE_TRANSFER' | 'OTHER'; export type PaymentDetail = {type?: PaymentType | undefined, payment_id?: string | undefined, payment_date?: DateNoTime | undefined, payment_date_time?: DateTime | undefined, method: PaymentMethod, note?: string | undefined, amount?: Money | undefined, shipping_info?: ContactNameAddress | undefined}; export type PaymentDetailList = Array; export type Payments = {paid_amount?: Money | undefined, transactions?: PaymentDetailList | undefined}; export type RefundDetail = {type?: PaymentType | undefined, refund_id?: string | undefined, refund_date?: DateNoTime | undefined, amount?: Money | undefined, method: PaymentMethod}; export type RefundDetailList = Array; export type Refunds = {refund_amount?: Money | undefined, transactions?: RefundDetailList | undefined}; export type LinkDescription = {href: string, rel: string, method?: ('GET' | 'POST' | 'PUT' | 'DELETE' | 'HEAD' | 'CONNECT' | 'OPTIONS' | 'PATCH') | undefined}; export type LinkDescriptionList = Array; export type Invoice = {id?: string | undefined, parent_id?: string | undefined, status?: InvoiceStatus | undefined, detail: InvoiceDetail, invoicer?: InvoicerInfo | undefined, primary_recipients?: RecipientInfoList | undefined, additional_recipients?: EmailAddressList | undefined, items?: ItemList | undefined, configuration?: Configuration | undefined, amount?: AmountSummaryDetail | undefined, due_amount?: Money | undefined, gratuity?: Money | undefined, payments?: Payments | undefined, refunds?: Refunds | undefined, links?: LinkDescriptionList | undefined}; export type CreateApiV2InvoicingInvoicesArgs = {body: Invoice}; export type CreateApiV2InvoicingInvoicesOptions = {baseUrl?: string | undefined, Oauth2?: string | undefined, fetch?: typeof fetch | undefined}; export const invoiceStatus = z.enum(["DRAFT", "SENT", "SCHEDULED", "PAID", "MARKED_AS_PAID", "CANCELLED", "REFUNDED", "PARTIALLY_PAID", "PARTIALLY_REFUNDED", "MARKED_AS_REFUNDED", "UNPAID", "PAYMENT_PENDING", "AUTO_CANCELLED", "PAID_EXTERNAL", "REFUNDED_EXTERNAL", "SHARED"]).max(255); export const currencyCode = z.string().min(3).max(3); export const dateTime = z.string().min(20).max(64); export const fileReference = z.object({id: z.string().min(1).max(255).optional(), reference_url: z.string().min(1).max(2000).optional(), content_type: z.string().optional(), create_time: dateTime.optional(), size: z.string().optional()}); export const fileReferenceList = z.array(fileReference); export const dateNoTime = z.string().min(10).max(10); export const paymentTermType = z.enum(["DUE_ON_RECEIPT", "DUE_ON_DATE_SPECIFIED", "NET_10", "NET_15", "NET_30", "NET_45", "NET_60", "NET_90", "NO_DUE_DATE"]).max(255); export const invoicePaymentTerm = z.object({term_type: paymentTermType.optional(), due_date: dateNoTime.optional()}); export const invoiceCreationFlow = z.enum(["MULTIPLE_RECIPIENTS_GROUP", "BATCH", "REGULAR_SINGLE"]).max(255); export const metadata = z.object({create_time: dateTime.optional(), created_by: z.string().max(2147483647).optional(), last_update_time: dateTime.optional(), last_updated_by: z.string().max(2147483647).optional(), cancel_time: dateTime.optional(), cancelled_by: z.string().optional(), first_sent_time: dateTime.optional(), last_sent_time: dateTime.optional(), last_sent_by: z.string().optional(), created_by_flow: invoiceCreationFlow.optional(), recipient_view_url: z.string().optional(), invoicer_view_url: z.string().optional()}); export const invoiceDetail = z.object({reference: z.string().max(120).optional(), currency_code: currencyCode, note: z.string().max(4000).optional(), terms_and_conditions: z.string().max(4000).optional(), memo: z.string().max(500).optional(), attachments: fileReferenceList.optional(), invoice_number: z.string().max(25).optional(), invoice_date: dateNoTime.optional(), payment_term: invoicePaymentTerm.optional(), metadata: metadata.optional()}); export const name = z.object({prefix: z.string().max(140).optional(), given_name: z.string().max(140).optional(), surname: z.string().max(140).optional(), middle_name: z.string().max(140).optional(), suffix: z.string().max(140).optional(), alternate_full_name: z.string().max(300).optional(), full_name: z.string().max(300).optional()}); export const countryCode = z.string().min(2).max(2); export const addressDetails = z.object({street_number: z.string().max(100).optional(), street_name: z.string().max(100).optional(), street_type: z.string().max(100).optional(), delivery_service: z.string().max(100).optional(), building_name: z.string().max(100).optional(), sub_building: z.string().max(100).optional()}); export const addressPortable = z.object({address_line_1: z.string().max(300).optional(), address_line_2: z.string().max(300).optional(), address_line_3: z.string().max(100).optional(), admin_area_4: z.string().max(100).optional(), admin_area_3: z.string().max(100).optional(), admin_area_2: z.string().max(120).optional(), admin_area_1: z.string().max(300).optional(), postal_code: z.string().max(60).optional(), country_code: countryCode, address_details: addressDetails.optional()}); export const restrictiveEmailAddress = z.string().min(3).max(254); export const phoneType = z.enum(["FAX", "HOME", "MOBILE", "OTHER", "PAGER"]); export const phoneDetail = z.object({country_code: z.string().min(1).max(3), national_number: z.string().min(1).max(14), extension_number: z.string().min(1).max(15).optional(), phone_type: phoneType}); export const phoneDetailList = z.array(phoneDetail); export const invoicerInfo = z.object({business_name: z.string().max(300).optional(), name: name.optional(), address: addressPortable.optional(), email_address: restrictiveEmailAddress.optional(), phones: phoneDetailList.optional(), website: z.string().max(2048).optional(), tax_id: z.string().max(100).optional(), additional_notes: z.string().max(400).optional(), logo_url: z.string().max(2000).optional()}); export const definitionsPhoneDetailList = z.array(phoneDetail); export const language = z.string().min(2).max(10); export const billingInfo = z.object({business_name: z.string().max(300).optional(), name: name.optional(), address: addressPortable.optional(), email_address: restrictiveEmailAddress.optional(), phones: definitionsPhoneDetailList.optional(), additional_info: z.string().max(40).optional(), language: language.optional()}); export const contactNameAddress = z.object({business_name: z.string().max(300).optional(), name: name.optional(), address: addressPortable.optional()}); export const recipientInfo = z.object({billing_info: billingInfo.optional(), shipping_info: contactNameAddress.optional()}); export const recipientInfoList = z.array(recipientInfo); export const emailAddress = z.string().min(3).max(254); export const emailAddressList = z.array(emailAddress); export const money = z.object({currency_code: currencyCode, value: z.string().max(32)}); export const percentage = z.string(); export const tax = z.object({name: z.string().max(100), percent: percentage, amount: money.optional(), tax_note: z.string().max(40).optional()}); export const discount = z.object({percent: percentage.optional(), amount: money.optional()}); export const unitOfMeasure = z.enum(["QUANTITY", "HOURS", "AMOUNT"]).max(2147483647); export const item = z.object({id: z.string().max(22).optional(), name: z.string().max(200), description: z.string().max(1000).optional(), quantity: z.string().max(14), unit_amount: money, tax: tax.optional(), item_date: dateNoTime.optional(), discount: discount.optional(), unit_of_measure: unitOfMeasure.optional()}); export const itemList = z.array(item); export const partialPayment = z.object({allow_partial_payment: z.boolean().optional(), minimum_amount_due: money.optional()}); export const configuration = z.object({tax_calculated_after_discount: z.boolean().optional(), tax_inclusive: z.boolean().optional(), allow_tip: z.boolean().optional(), partial_payment: partialPayment.optional(), has_conditional_rule: z.boolean().optional(), template_id: z.string().max(30).optional()}); export const aggregatedDiscount = z.object({invoice_discount: discount.optional(), item_discount: money.optional()}); export const shippingCost = z.object({amount: money.optional(), tax: tax.optional()}); export const customAmount = z.object({label: z.string().max(50), amount: money.optional()}); export const amountWithBreakdown = z.object({item_total: money.optional(), discount: aggregatedDiscount.optional(), tax_total: money.optional(), shipping: shippingCost.optional(), custom: customAmount.optional()}); export const amountSummaryDetail = z.object({currency_code: currencyCode.optional(), value: z.string().max(32).optional(), breakdown: amountWithBreakdown.optional()}); export const paymentType = z.enum(["PAYPAL", "EXTERNAL"]).max(255); export const paymentMethod = z.enum(["BANK_TRANSFER", "CASH", "CHECK", "CREDIT_CARD", "DEBIT_CARD", "PAYPAL", "WIRE_TRANSFER", "OTHER"]).max(255); export const paymentDetail = z.object({type: paymentType.optional(), payment_id: z.string().max(22).optional(), payment_date: dateNoTime.optional(), payment_date_time: dateTime.optional(), method: paymentMethod, note: z.string().max(2000).optional(), amount: money.optional(), shipping_info: contactNameAddress.optional()}); export const paymentDetailList = z.array(paymentDetail); export const payments = z.object({paid_amount: money.optional(), transactions: paymentDetailList.optional()}); export const refundDetail = z.object({type: paymentType.optional(), refund_id: z.string().max(22).optional(), refund_date: dateNoTime.optional(), amount: money.optional(), method: paymentMethod}); export const refundDetailList = z.array(refundDetail); export const refunds = z.object({refund_amount: money.optional(), transactions: refundDetailList.optional()}); export const linkDescription = z.object({href: z.string(), rel: z.string(), method: z.enum(["GET", "POST", "PUT", "DELETE", "HEAD", "CONNECT", "OPTIONS", "PATCH"]).optional()}); export const linkDescriptionList = z.array(linkDescription); export const invoice = z.object({id: z.string().max(30).optional(), parent_id: z.string().max(30).optional(), status: invoiceStatus.optional(), detail: invoiceDetail, invoicer: invoicerInfo.optional(), primary_recipients: recipientInfoList.optional(), additional_recipients: emailAddressList.optional(), items: itemList.optional(), configuration: configuration.optional(), amount: amountSummaryDetail.optional(), due_amount: money.optional(), gratuity: money.optional(), payments: payments.optional(), refunds: refunds.optional(), links: linkDescriptionList.optional()}); 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 }; /** * Create draft invoice * * POST /v2/invoicing/invoices */ export const createApiV2InvoicingInvoices = async (args: CreateApiV2InvoicingInvoicesArgs, options?: CreateApiV2InvoicingInvoicesOptions) => { const {baseUrl = "https://api-m.paypal.com", fetch: fetchFn = fetch, Oauth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (Oauth2 !== undefined) headers.set('authorization', `Bearer ${Oauth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/v2/invoicing/invoices${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", 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(invoice, await res.json()) };