/**
* Scaffolded PayPal OpenAPI clients (dependency-free ESM).
*
* Sources (openapi_client_scaffold, auth kind: none — bearer injected by package auth layer):
* - https://raw.githubusercontent.com/paypal/paypal-rest-api-specifications/main/openapi/invoicing_v2.json
* slugs: invoices_list, invoices_get, invoices_search_invoices, invoices_create, invoices_send
* - https://raw.githubusercontent.com/paypal/paypal-rest-api-specifications/main/openapi/reporting_transactions_v1.json
* slugs: search_get, balances_get
* - https://raw.githubusercontent.com/paypal/paypal-rest-api-specifications/main/openapi/payments_payouts_batch_v1.json
* slugs: payouts_create, payouts_get, payouts_item_get
*
* Host approval stays in the account security UI; the OpenAPI spec never widens it.
*/
export type QueryValue = string | number | boolean | null | undefined
export type QueryInput = Record<string, QueryValue | QueryValue[]>
export type ScaffoldInput = {
params?: Record<string, unknown>
query?: QueryInput
headers?: Record<string, string>
body?: unknown
}
export type ScaffoldOptions = {
fetchImpl?: typeof fetch
/** Override the default live API base (e.g. sandbox). */
apiBaseUrl?: string
}
const DEFAULT_API_BASE_URL = 'https://api-m.paypal.com'
function resolveApiBaseUrl(options: ScaffoldOptions = {}): string {
const base = options.apiBaseUrl ?? DEFAULT_API_BASE_URL
return String(base).replace(/\/+$/, '')
}
export function buildUrl(
pathTemplate: string,
params: Record<string, unknown> = {},
apiBaseUrl: string = DEFAULT_API_BASE_URL,
): string {
return apiBaseUrl + pathTemplate.replace(/\{([^}]+)\}/g, (_match, name: string) => {
const value = params[name]
if (value === undefined || value === null) {
throw new Error(`Missing required path parameter: ${name}`)
}
return encodeURIComponent(String(value))
})
}
export function appendQuery(url: string, query: QueryInput = {}): string {
const search = new URLSearchParams()
for (const [key, value] of Object.entries(query)) {
if (value === undefined || value === null || value === '') continue
if (Array.isArray(value)) {
for (const item of value) {
if (item === undefined || item === null || item === '') continue
search.append(key, String(item))
}
continue
}
search.append(key, String(value))
}
const qs = search.toString()
return qs ? `${url}?${qs}` : url
}
function mergeHeaders(
userHeaders: Record<string, string> | undefined,
authHeaders: Record<string, string>,
): Record<string, string> {
const merged: Record<string, string> = { ...(userHeaders ?? {}) }
for (const [key, value] of Object.entries(authHeaders)) {
const lower = key.toLowerCase()
for (const existing of Object.keys(merged)) {
if (existing.toLowerCase() === lower) delete merged[existing]
}
merged[key] = value
}
return merged
}
function hasHeader(headers: Record<string, string>, name: string): boolean {
const lower = name.toLowerCase()
return Object.keys(headers).some((key) => key.toLowerCase() === lower)
}
async function resolveFetch(fetchImpl?: typeof fetch): Promise<typeof fetch> {
return fetchImpl ?? fetch
}
/** Scaffold auth kind was `none`; callers inject Authorization via input.headers. */
function authHeaders(): Record<string, string> {
return {}
}
async function request(
method: string,
pathTemplate: string,
input: ScaffoldInput = {},
options: ScaffoldOptions = {},
): Promise<Response> {
const params = input.params ?? {}
const apiBaseUrl = resolveApiBaseUrl(options)
const url = appendQuery(buildUrl(pathTemplate, params, apiBaseUrl), input.query)
let body: string | undefined
const headers = mergeHeaders(input.headers, authHeaders())
if (input.body !== undefined) {
body = JSON.stringify(input.body)
if (!hasHeader(headers, 'content-type')) {
headers['content-type'] = 'application/json'
}
}
const fetchImpl = await resolveFetch(options.fetchImpl)
return fetchImpl(url, { method, headers, body })
}
/** GET /v2/invoicing/invoices — List invoices */
export async function invoicesList(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
return request('GET', '/v2/invoicing/invoices', input, options)
}
/** GET /v2/invoicing/invoices/{invoice_id} — Show invoice details */
export async function invoicesGet(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
const params = input.params ?? {}
if (params.invoice_id === undefined || params.invoice_id === null) {
throw new Error('Missing required path parameter: invoice_id')
}
return request('GET', '/v2/invoicing/invoices/{invoice_id}', input, options)
}
/** POST /v2/invoicing/search-invoices — Search for invoices (read-only search) */
export async function invoicesSearchInvoices(
input: ScaffoldInput = {},
options: ScaffoldOptions = {},
): Promise<Response> {
return request('POST', '/v2/invoicing/search-invoices', input, options)
}
/** POST /v2/invoicing/invoices — Create draft invoice */
export async function invoicesCreate(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
return request('POST', '/v2/invoicing/invoices', input, options)
}
/** POST /v2/invoicing/invoices/{invoice_id}/send — Send an invoice */
export async function invoicesSend(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
const params = input.params ?? {}
if (params.invoice_id === undefined || params.invoice_id === null) {
throw new Error('Missing required path parameter: invoice_id')
}
return request('POST', '/v2/invoicing/invoices/{invoice_id}/send', input, options)
}
/** GET /v1/reporting/transactions — List transactions */
export async function searchGet(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
return request('GET', '/v1/reporting/transactions', input, options)
}
/** GET /v1/reporting/balances — List all balances */
export async function balancesGet(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
return request('GET', '/v1/reporting/balances', input, options)
}
/** POST /v1/payments/payouts — Create a batch payout */
export async function payoutsCreate(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
return request('POST', '/v1/payments/payouts', input, options)
}
/** GET /v1/payments/payouts/{payout_batch_id} — Show payout batch details */
export async function payoutsGet(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
const params = input.params ?? {}
if (params.payout_batch_id === undefined || params.payout_batch_id === null) {
throw new Error('Missing required path parameter: payout_batch_id')
}
return request('GET', '/v1/payments/payouts/{payout_batch_id}', input, options)
}
/** GET /v1/payments/payouts-item/{payout_item_id} — Show payout item details */
export async function payoutsItemGet(input: ScaffoldInput = {}, options: ScaffoldOptions = {}): Promise<Response> {
const params = input.params ?? {}
if (params.payout_item_id === undefined || params.payout_item_id === null) {
throw new Error('Missing required path parameter: payout_item_id')
}
return request('GET', '/v1/payments/payouts-item/{payout_item_id}', input, options)
}